示例#1
0
    def __getattr__(self, key):
        """Return a grib key, or one of our extra keys."""

        # is it in the grib message?
        try:
            # we just get <type 'float'> as the type of the "values" array...special case here...
            if key in ["values", "pv", "latitudes", "longitudes"]:
                res = gribapi.grib_get_double_array(self.grib_message, key)
            elif key in ('typeOfFirstFixedSurface', 'typeOfSecondFixedSurface'):
                res = np.int32(gribapi.grib_get_long(self.grib_message, key))
            else:
                key_type = gribapi.grib_get_native_type(self.grib_message, key)
                if key_type == int:
                    res = np.int32(gribapi.grib_get_long(self.grib_message, key))
                elif key_type == float:
                    # Because some computer keys are floats, like
                    # longitudeOfFirstGridPointInDegrees, a float32 is not always enough...
                    res = np.float64(gribapi.grib_get_double(self.grib_message, key))
                elif key_type == str:
                    res = gribapi.grib_get_string(self.grib_message, key)
                else:
                    raise ValueError("Unknown type for %s : %s" % (key, str(key_type)))
        except gribapi.GribInternalError:
            res = None

        #...or is it in our list of extras?
        if res is None:
            if key in self.extra_keys:
                res = self.extra_keys[key]
            else:
                #must raise an exception for the hasattr() mechanism to work
                raise AttributeError("Cannot find GRIB key %s" % key)

        return res
示例#2
0
    def __getattr__(self, key):
        """Return a grib key, or one of our extra keys."""

        # is it in the grib message?
        try:
            # we just get <type 'float'> as the type of the "values" array...special case here...
            if key in ["values", "pv", "latitudes", "longitudes"]:
                res = gribapi.grib_get_double_array(self.grib_message, key)
            elif key in ('typeOfFirstFixedSurface', 'typeOfSecondFixedSurface'):
                res = np.int32(gribapi.grib_get_long(self.grib_message, key))
            else:
                key_type = gribapi.grib_get_native_type(self.grib_message, key)
                if key_type == int:
                    res = np.int32(gribapi.grib_get_long(self.grib_message, key))
                elif key_type == float:
                    # Because some computer keys are floats, like
                    # longitudeOfFirstGridPointInDegrees, a float32 is not always enough...
                    res = np.float64(gribapi.grib_get_double(self.grib_message, key))
                elif key_type == str:
                    res = gribapi.grib_get_string(self.grib_message, key)
                else:
                    raise ValueError("Unknown type for %s : %s" % (key, str(key_type)))
        except gribapi.GribInternalError:
            res = None

        #...or is it in our list of extras?
        if res is None:
            if key in self.extra_keys:
                res = self.extra_keys[key]
            else:
                #must raise an exception for the hasattr() mechanism to work
                raise AttributeError("Cannot find GRIB key %s" % key)

        return res
示例#3
0
def grid_definition_template_12(cube, grib):
    """
    Set keys within the provided grib message based on
    Grid Definition Template 3.12.

    Template 3.12 is used to represent a Transverse Mercator grid.

    """
    gribapi.grib_set(grib, "gridDefinitionTemplateNumber", 12)

    # Retrieve some information from the cube.
    y_coord = cube.coord(dimensions=[0])
    x_coord = cube.coord(dimensions=[1])
    cs = y_coord.coord_system

    # Normalise the coordinate values to centimetres - the resolution
    # used in the GRIB message.
    def points_in_cm(coord):
        points = coord.units.convert(coord.points, 'cm')
        points = np.around(points).astype(int)
        return points

    y_cm = points_in_cm(y_coord)
    x_cm = points_in_cm(x_coord)

    # Set some keys specific to GDT12.
    # Encode the horizontal points.

    # NB. Since we're already in centimetres, our tolerance for
    # discrepancy in the differences is 1.
    def step(points):
        diffs = points[1:] - points[:-1]
        mean_diff = np.mean(diffs).astype(points.dtype)
        if not np.allclose(diffs, mean_diff, atol=1):
            msg = ('Irregular coordinates not supported for transverse '
                   'Mercator.')
            raise iris.exceptions.TranslationError(msg)
        return int(mean_diff)

    gribapi.grib_set(grib, 'Di', abs(step(x_cm)))
    gribapi.grib_set(grib, 'Dj', abs(step(y_cm)))
    horizontal_grid_common(cube, grib)

    # GRIBAPI expects unsigned ints in X1, X2, Y1, Y2 but it should accept
    # signed ints, so work around this.
    # See https://software.ecmwf.int/issues/browse/SUP-1101
    ensure_set_int32_value(grib, 'Y1', int(y_cm[0]))
    ensure_set_int32_value(grib, 'Y2', int(y_cm[-1]))
    ensure_set_int32_value(grib, 'X1', int(x_cm[0]))
    ensure_set_int32_value(grib, 'X2', int(x_cm[-1]))

    # Lat and lon of reference point are measured in millionths of a degree.
    gribapi.grib_set(grib, "latitudeOfReferencePoint",
                     cs.latitude_of_projection_origin / _DEFAULT_DEGREES_UNITS)
    gribapi.grib_set(grib, "longitudeOfReferencePoint",
                     cs.longitude_of_central_meridian / _DEFAULT_DEGREES_UNITS)

    # Convert a value in metres into the closest integer number of
    # centimetres.
    def m_to_cm(value):
        return int(round(value * 100))

    # False easting and false northing are measured in units of (10^-2)m.
    gribapi.grib_set(grib, 'XR', m_to_cm(cs.false_easting))
    gribapi.grib_set(grib, 'YR', m_to_cm(cs.false_northing))

    # GRIBAPI expects a signed int for scaleFactorAtReferencePoint
    # but it should accept a float, so work around this.
    # See https://software.ecmwf.int/issues/browse/SUP-1100
    value = cs.scale_factor_at_central_meridian
    key_type = gribapi.grib_get_native_type(grib,
                                            "scaleFactorAtReferencePoint")
    if key_type is not float:
        value = fixup_float32_as_int32(value)
    gribapi.grib_set(grib, "scaleFactorAtReferencePoint", value)
示例#4
0
def grid_definition_template_12(cube, grib):
    """
    Set keys within the provided grib message based on
    Grid Definition Template 3.12.

    Template 3.12 is used to represent a Transverse Mercator grid.

    """
    gribapi.grib_set(grib, "gridDefinitionTemplateNumber", 12)

    # Retrieve some information from the cube.
    y_coord = cube.coord(dimensions=[0])
    x_coord = cube.coord(dimensions=[1])
    cs = y_coord.coord_system

    # Normalise the coordinate values to centimetres - the resolution
    # used in the GRIB message.
    def points_in_cm(coord):
        points = coord.units.convert(coord.points, 'cm')
        points = np.around(points).astype(int)
        return points
    y_cm = points_in_cm(y_coord)
    x_cm = points_in_cm(x_coord)

    # Set some keys specific to GDT12.
    # Encode the horizontal points.

    # NB. Since we're already in centimetres, our tolerance for
    # discrepancy in the differences is 1.
    def step(points):
        diffs = points[1:] - points[:-1]
        mean_diff = np.mean(diffs).astype(points.dtype)
        if not np.allclose(diffs, mean_diff, atol=1):
            msg = ('Irregular coordinates not supported for transverse '
                   'Mercator.')
            raise iris.exceptions.TranslationError(msg)
        return int(mean_diff)

    gribapi.grib_set(grib, 'Di', abs(step(x_cm)))
    gribapi.grib_set(grib, 'Dj', abs(step(y_cm)))
    horizontal_grid_common(cube, grib)

    # GRIBAPI expects unsigned ints in X1, X2, Y1, Y2 but it should accept
    # signed ints, so work around this.
    # See https://software.ecmwf.int/issues/browse/SUP-1101
    ensure_set_int32_value(grib, 'Y1', int(y_cm[0]))
    ensure_set_int32_value(grib, 'Y2', int(y_cm[-1]))
    ensure_set_int32_value(grib, 'X1', int(x_cm[0]))
    ensure_set_int32_value(grib, 'X2', int(x_cm[-1]))

    # Lat and lon of reference point are measured in millionths of a degree.
    gribapi.grib_set(grib, "latitudeOfReferencePoint",
                     cs.latitude_of_projection_origin / _DEFAULT_DEGREES_UNITS)
    gribapi.grib_set(grib, "longitudeOfReferencePoint",
                     cs.longitude_of_central_meridian / _DEFAULT_DEGREES_UNITS)

    # Convert a value in metres into the closest integer number of
    # centimetres.
    def m_to_cm(value):
        return int(round(value * 100))

    # False easting and false northing are measured in units of (10^-2)m.
    gribapi.grib_set(grib, 'XR', m_to_cm(cs.false_easting))
    gribapi.grib_set(grib, 'YR', m_to_cm(cs.false_northing))

    # GRIBAPI expects a signed int for scaleFactorAtReferencePoint
    # but it should accept a float, so work around this.
    # See https://software.ecmwf.int/issues/browse/SUP-1100
    value = cs.scale_factor_at_central_meridian
    key_type = gribapi.grib_get_native_type(grib,
                                            "scaleFactorAtReferencePoint")
    if key_type is not float:
        value = fixup_float32_as_int32(value)
    gribapi.grib_set(grib, "scaleFactorAtReferencePoint", value)