Example #1
0
 def test_time_as_number(self):
     # Make sure Coord.cell() normally returns the values straight
     # out of the Coord's points/bounds arrays.
     coord = self._mock_coord()
     cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.time)
     self.assertEqual(cell.bound,
                      (mock.sentinel.lower, mock.sentinel.upper))
Example #2
0
 def test_time_as_number(self):
     # Make sure Coord.cell() normally returns the values straight
     # out of the Coord's points/bounds arrays.
     coord = self._mock_coord()
     cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.time)
     self.assertEquals(cell.bound,
                       (mock.sentinel.lower, mock.sentinel.upper))
Example #3
0
 def _add_forecast_reference_time(input_time: Coord, advected_cube: Cube) -> None:
     """Add or replace a forecast reference time on the advected cube"""
     try:
         advected_cube.remove_coord("forecast_reference_time")
     except CoordinateNotFoundError:
         pass
     frt_coord_name = "forecast_reference_time"
     frt_coord_spec = TIME_COORDS[frt_coord_name]
     frt_coord = input_time.copy()
     frt_coord.rename(frt_coord_name)
     frt_coord.convert_units(frt_coord_spec.units)
     frt_coord.points = round_close(frt_coord.points, dtype=frt_coord_spec.dtype)
     advected_cube.add_aux_coord(frt_coord)
Example #4
0
def pad_coord(coord: Coord, width: int, method: str) -> Coord:
    """
    Construct a new coordinate by extending the current coordinate by the
    padding width.

    Args:
        coord:
            Original coordinate which will be used as the basis of the
            new extended coordinate.
        width:
            The width of padding in grid cells (the extent of the
            neighbourhood radius in grid cells in a given direction).
        method:
            A string determining whether the coordinate is being expanded
            or contracted. Options: 'remove' to remove points from coord;
            'add' to add points to coord.

    Returns:
        Coordinate with expanded or contracted length, to be added to
        the padded or unpadded iris cube.

    Raises:
        ValueError: Raise an error if non-uniform increments exist between
                    grid points.
    """
    orig_points = coord.points
    increment = orig_points[1:] - orig_points[:-1]
    if np.isclose(np.sum(np.diff(increment)), 0):
        increment = increment[0]
    else:
        msg = "Non-uniform increments between grid points: " "{}.".format(
            increment)
        raise ValueError(msg)

    if method == "add":
        num_of_new_points = len(orig_points) + width + width
        new_points = np.linspace(
            orig_points[0] - width * increment,
            orig_points[-1] + width * increment,
            num_of_new_points,
            dtype=np.float32,
        )
    elif method == "remove":
        end_width = -width if width != 0 else None
        new_points = np.float32(orig_points[width:end_width])
    new_points = new_points.astype(orig_points.dtype)

    new_points_bounds = np.array(
        [new_points - 0.5 * increment, new_points + 0.5 * increment],
        dtype=np.float32).T
    return coord.copy(points=new_points, bounds=new_points_bounds)
Example #5
0
 def test_time_as_object(self):
     # Ensure Coord.cell() converts the point/bound values to
     # "datetime" objects.
     coord = self._mock_coord()
     coord.units.num2date = mock.Mock(
         side_effect=[mock.sentinel.datetime,
                      (mock.sentinel.datetime_lower,
                       mock.sentinel.datetime_upper)])
     cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.datetime)
     self.assertEqual(cell.bound,
                      (mock.sentinel.datetime_lower,
                       mock.sentinel.datetime_upper))
     self.assertEqual(coord.units.num2date.call_args_list,
                      [mock.call((mock.sentinel.time,)),
                       mock.call((mock.sentinel.lower,
                                  mock.sentinel.upper))])
Example #6
0
 def test_time_as_object(self):
     # Ensure Coord.cell() converts the point/bound values to
     # "datetime" objects.
     coord = self._mock_coord()
     coord.units.num2date = mock.Mock(side_effect=[
         mock.sentinel.datetime,
         (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)
     ])
     cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.datetime)
     self.assertEqual(
         cell.bound,
         (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper))
     self.assertEqual(coord.units.num2date.call_args_list, [
         mock.call((mock.sentinel.time, )),
         mock.call((mock.sentinel.lower, mock.sentinel.upper))
     ])
Example #7
0
 def test_time_as_object(self):
     # When iris.FUTURE.cell_datetime_objects is True, ensure
     # Coord.cell() converts the point/bound values to "datetime"
     # objects.
     coord = self._mock_coord()
     coord.units.num2date = mock.Mock(
         side_effect=[mock.sentinel.datetime,
                      (mock.sentinel.datetime_lower,
                       mock.sentinel.datetime_upper)])
     with mock.patch('iris.FUTURE', cell_datetime_objects=True):
         cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.datetime)
     self.assertEqual(cell.bound,
                      (mock.sentinel.datetime_lower,
                       mock.sentinel.datetime_upper))
     self.assertEqual(coord.units.num2date.call_args_list,
                      [mock.call((mock.sentinel.time,)),
                       mock.call((mock.sentinel.lower,
                                  mock.sentinel.upper))])
Example #8
0
def iris_time_to_datetime(time_coord: Coord,
                          point_or_bound: str = "point") -> List[datetime]:
    """
    Convert iris time to python datetime object. Working in UTC.

    Args:
        time_coord:
            Iris time coordinate element(s).

    Returns:
        The time element(s) recast as a python datetime object.
    """
    coord = time_coord.copy()
    coord.convert_units("seconds since 1970-01-01 00:00:00")
    if point_or_bound == "point":
        datetime_list = [value.point for value in coord.cells()]
    elif point_or_bound == "bound":
        datetime_list = [value.bound for value in coord.cells()]
    return datetime_list
Example #9
0
 def test_time_as_object(self):
     # When iris.FUTURE.cell_datetime_objects is True, ensure
     # Coord.cell() converts the point/bound values to "datetime"
     # objects.
     coord = self._mock_coord()
     coord.units.num2date = mock.Mock(side_effect=[
         mock.sentinel.datetime,
         (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)
     ])
     with mock.patch('iris.FUTURE', cell_datetime_objects=True):
         cell = Coord.cell(coord, 0)
     self.assertIs(cell.point, mock.sentinel.datetime)
     self.assertEquals(
         cell.bound,
         (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper))
     self.assertEqual(coord.units.num2date.call_args_list, [
         mock.call((mock.sentinel.time, )),
         mock.call((mock.sentinel.lower, mock.sentinel.upper))
     ])
Example #10
0
    def _update_time(input_time: Coord, advected_cube: Cube,
                     timestep: timedelta) -> None:
        """Increment validity time on the advected cube

        Args:
            input_time:
                Time coordinate from source cube
            advected_cube:
                Cube containing advected data (modified in place)
            timestep:
                Time difference between the advected output and the source
        """
        original_datetime = next(input_time.cells())[0]
        new_datetime = original_datetime + timestep
        new_time = input_time.units.date2num(new_datetime)
        time_coord_name = "time"
        time_coord_spec = TIME_COORDS[time_coord_name]
        time_coord = advected_cube.coord(time_coord_name)
        time_coord.points = new_time
        time_coord.convert_units(time_coord_spec.units)
        time_coord.points = round_close(time_coord.points,
                                        dtype=time_coord_spec.dtype)
Example #11
0
 def test_coord_stash(self):
     token = 'stash'
     coord = Coord(1, attributes=dict(STASH=token))
     self._check(token, coord)
Example #12
0
 def grid_spacing(coord: Coord) -> float:
     """Calculate grid spacing along a given spatial axis"""
     new_coord = coord.copy()
     new_coord.convert_units("m")
     return np.float32(np.diff((new_coord).points)[0])
Example #13
0
 def test(self):
     emsg = ("Can't instantiate abstract class Coord with abstract"
             " methods __init__")
     with self.assertRaisesRegex(TypeError, emsg):
         _ = Coord(points=[0, 1])
Example #14
0
def _calculate_forecast_period(
    time_coord: Coord,
    frt_coord: Coord,
    dim_coord: bool = False,
    coord_spec: TimeSpec = TIME_COORDS["forecast_period"],
) -> Coord:
    """
    Calculate a forecast period from existing time and forecast reference
    time coordinates.

    Args:
        time_coord:
            Time coordinate
        frt_coord:
            Forecast reference coordinate
        dim_coord:
            If true, create an iris.coords.DimCoord instance.  Default is to
            create an iris.coords.AuxCoord.
        coord_spec:
            Specification of units and dtype for the forecast_period
            coordinate.

    Returns:
        Forecast period coordinate corresponding to the input times and
        forecast reference times specified

    Warns:
        UserWarning: If any calculated forecast periods are negative
    """
    # use cell() access method to get datetime.datetime instances
    time_points = np.array([c.point for c in time_coord.cells()])
    forecast_reference_time_points = np.array([c.point for c in frt_coord.cells()])
    required_lead_times = time_points - forecast_reference_time_points
    required_lead_times = np.array([x.total_seconds() for x in required_lead_times])

    if time_coord.bounds is not None:
        time_bounds = np.array([c.bound for c in time_coord.cells()])
        required_lead_time_bounds = time_bounds - forecast_reference_time_points
        required_lead_time_bounds = np.array(
            [[b.total_seconds() for b in x] for x in required_lead_time_bounds]
        )
    else:
        required_lead_time_bounds = None

    coord_type = DimCoord if dim_coord else AuxCoord
    result_coord = coord_type(
        required_lead_times,
        standard_name="forecast_period",
        bounds=required_lead_time_bounds,
        units="seconds",
    )

    result_coord.convert_units(coord_spec.units)

    if coord_spec.dtype not in FLOAT_TYPES:
        result_coord.points = round_close(result_coord.points)
        if result_coord.bounds is not None:
            result_coord.bounds = round_close(result_coord.bounds)

    result_coord.points = result_coord.points.astype(coord_spec.dtype)
    if result_coord.bounds is not None:
        result_coord.bounds = result_coord.bounds.astype(coord_spec.dtype)

    if np.any(result_coord.points < 0):
        msg = (
            "The values for the time {} and "
            "forecast_reference_time {} coordinates from the "
            "input cube have produced negative values for the "
            "forecast_period. A forecast does not generate "
            "values in the past."
        ).format(time_coord.points, frt_coord.points)
        warnings.warn(msg)

    return result_coord
Example #15
0
 def test_coord_standard_name(self):
     token = 'air_temperature'
     coord = Coord(1, standard_name=token)
     self._check(token, coord)
Example #16
0
 def test_mixture_default(self):
     token = 'air temperature'  # includes space
     coord = Coord(1, long_name=token)
     result = CellMethod(self.method, coords=[coord, token])
     expected = '{}: unknown, unknown'.format(self.method, token, token)
     self.assertEqual(str(result), expected)
Example #17
0
 def test_mixture(self):
     token = 'air_temperature'
     coord = Coord(1, standard_name=token)
     result = CellMethod(self.method, coords=[coord, token])
     expected = '{}: {}, {}'.format(self.method, token, token)
     self.assertEqual(str(result), expected)
Example #18
0
 def test_coord_stash_default(self):
     token = '_stash'  # includes leading underscore
     coord = Coord(1, attributes=dict(STASH=token))
     self._check(token, coord, default=True)
Example #19
0
 def test_coord_var_name_fail(self):
     token = 'var name'  # includes space
     emsg = 'is not a valid NetCDF variable name'
     with self.assertRaisesRegexp(ValueError, emsg):
         Coord(1, var_name=token)
Example #20
0
 def test_coord_var_name(self):
     token = 'var_name'
     coord = Coord(1, var_name=token)
     self._check(token, coord)
Example #21
0
 def test_coord_long_name_default(self):
     token = 'long name'  # includes space
     coord = Coord(1, long_name=token)
     self._check(token, coord, default=True)
Example #22
0
 def test_coord_long_name(self):
     token = 'long_name'
     coord = Coord(1, long_name=token)
     self._check(token, coord)