示例#1
0
    def _regularise_shape(grib_message):
        """
        Calculate the regularised shape of the reduced message and push
        dummy regularised values into the message to force the gribapi
        to update the message grid type from reduced to regular.

        """
        # Make sure to read any missing values as NaN.
        gribapi.grib_set_double(grib_message, "missingValue", np.nan)

        # Get full longitude values, these describe the longitude value of
        # *every* point in the grid, they are not 1d monotonic coordinates.
        lons = gribapi.grib_get_double_array(grib_message, "longitudes")

        # Compute the new longitude coordinate for the regular grid.
        new_nx = max(gribapi.grib_get_long_array(grib_message, "pl"))
        new_x_step = (max(lons) - min(lons)) / (new_nx - 1)
        if gribapi.grib_get_long(grib_message, "iScansNegatively"):
            new_x_step *= -1

        gribapi.grib_set_long(grib_message, "Nx", int(new_nx))
        gribapi.grib_set_double(grib_message, "iDirectionIncrementInDegrees",
                                float(new_x_step))
        # Spoof gribapi with false regularised values.
        nj = gribapi.grib_get_long(grib_message, 'Nj')
        temp = np.zeros((nj * new_nx,), dtype=np.float)
        gribapi.grib_set_double_array(grib_message, 'values', temp)
        gribapi.grib_set_long(grib_message, "jPointsAreConsecutive", 0)
        gribapi.grib_set_long(grib_message, "PLPresent", 0)
示例#2
0
    def _regularise_shape(grib_message):
        """
        Calculate the regularised shape of the reduced message and push
        dummy regularised values into the message to force the gribapi
        to update the message grid type from reduced to regular.

        """
        # Make sure to read any missing values as NaN.
        gribapi.grib_set_double(grib_message, "missingValue", np.nan)

        # Get full longitude values, these describe the longitude value of
        # *every* point in the grid, they are not 1d monotonic coordinates.
        lons = gribapi.grib_get_double_array(grib_message, "longitudes")

        # Compute the new longitude coordinate for the regular grid.
        new_nx = max(gribapi.grib_get_long_array(grib_message, "pl"))
        new_x_step = (max(lons) - min(lons)) / (new_nx - 1)
        if gribapi.grib_get_long(grib_message, "iScansNegatively"):
            new_x_step *= -1

        gribapi.grib_set_long(grib_message, "Nx", int(new_nx))
        gribapi.grib_set_double(grib_message, "iDirectionIncrementInDegrees",
                                float(new_x_step))
        # Spoof gribapi with false regularised values.
        nj = gribapi.grib_get_long(grib_message, 'Nj')
        temp = np.zeros((nj * new_nx,), dtype=np.float)
        gribapi.grib_set_double_array(grib_message, 'values', temp)
        gribapi.grib_set_long(grib_message, "jPointsAreConsecutive", 0)
        gribapi.grib_set_long(grib_message, "PLPresent", 0)
示例#3
0
def set_data(source, grib):
    """
    Sets the actual data of a grib message.
    """
    var_name = get_varible_name(source)
    # treat masked arrays differently
    if isinstance(source[var_name].values, np.ma.core.MaskedArray):
        gribapi.grib_set(grib, "bitmapPresent", 1)
        # use the missing value from the masked array as default
        missing_value = source[var_name].values.get_fill_value()
        # but give the netCDF specified missing value preference
        missing_value = source[var_name].attrs.get('missing_value',
                                                        missing_value)
        gribapi.grib_set_double(grib, "missingValue",
                                float(missing_value))
        data = source[var_name].values.filled()
    else:
        gribapi.grib_set_double(grib, "missingValue", 9999)
        data = source[var_name].values[:]
    gribapi.grib_set_long(grib, "bitsPerValue", 12)
    #gribapi.grib_set_long(grib, "bitsPerValueAndRepack", 12)
    gribapi.grib_set_long(grib, "decimalPrecision", 2)
    gribapi.grib_set_long(grib, "decimalScaleFactor", 2)
    #gribapi.grib_set_long(grib, "binaryScaleFactor", 0)
    gribapi.grib_set_long(grib, "dataRepresentationType", 0)
    # get the grib code for the variable
    code = reverse_codes[conv.to_grib1[var_name]]
    _, grib_unit = codes[code]
    # default to the grib default unit
    unit = source[var_name].attrs.get('units', grib_unit)
    mult = 1.
    if not unit == grib_unit:
        mult = units._speed[unit] / units._speed[grib_unit]
    # add the data
    gribapi.grib_set_double_array(grib, "values", mult * data.flatten())
示例#4
0
def data(cube, grib):

    # mdi
    if isinstance(cube.data, numpy.ma.core.MaskedArray):
        gribapi.grib_set_long(grib, "missingValue", cube.data.fill_value)
        data = cube.data.filled()
    else:
        gribapi.grib_set_long(grib, "missingValue", -1e9)
        data = cube.data
    
    # values
    gribapi.grib_set_double_array(grib, "values", data.flatten())
示例#5
0
def randomise_grib(filename):
    """Randomise the data in the given GRIB file."""
    in_file = open(filename, "rb")
    out_file = open("out.grib", "wb")

    while True:
        grib_message = gribapi.grib_new_from_file(in_file)
        if not grib_message:
            break

        values = gribapi.grib_get_double_array(grib_message, "values")
        values = numpy.random.rand(len(values))
        gribapi.grib_set_double_array(grib_message, "values", values)
        gribapi.grib_write(grib_message, out_file)

    os.remove(filename)
    os.rename("out.grib", filename)
示例#6
0
def randomise_grib(filename):
	"""Randomise the data in the given GRIB file."""
	in_file = open(filename, "rb")
	out_file = open("out.grib", "wb")
	
	while True:
		grib_message = gribapi.grib_new_from_file(in_file)
		if not grib_message:
			break
			
		values = gribapi.grib_get_double_array(grib_message, "values")
		values = numpy.random.rand(len(values))
		gribapi.grib_set_double_array(grib_message, "values", values)
		gribapi.grib_write(grib_message, out_file)
		
	os.remove(filename)
	os.rename("out.grib", filename)
示例#7
0
def data_section(cube, grib):
    # Masked data?
    if isinstance(cube.data, ma.core.MaskedArray):
        # What missing value shall we use?
        if not np.isnan(cube.data.fill_value):
            # Use the data's fill value.
            fill_value = float(cube.data.fill_value)
        else:
            # We can't use the data's fill value if it's NaN,
            # the GRIB API doesn't like it.
            # Calculate an MDI outside the data range.
            min, max = cube.data.min(), cube.data.max()
            fill_value = min - (max - min) * 0.1
        # Prepare the unmaksed data array, using fill_value as the MDI.
        data = cube.data.filled(fill_value)
    else:
        fill_value = None
        data = cube.data

    # units scaling
    grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name,
                                              cube.long_name)
    if grib2_info is None:
        # for now, just allow this
        warnings.warn('Unable to determine Grib2 parameter code for cube.\n'
                      'Message data may not be correctly scaled.')
    else:
        if cube.units != grib2_info.units:
            data = cube.units.convert(data, grib2_info.units)
            if fill_value is not None:
                fill_value = cube.units.convert(fill_value, grib2_info.units)

    if fill_value is None:
        # Disable missing values in the grib message.
        gribapi.grib_set(grib, "bitmapPresent", 0)
    else:
        # Enable missing values in the grib message.
        gribapi.grib_set(grib, "bitmapPresent", 1)
        gribapi.grib_set_double(grib, "missingValue", fill_value)
    gribapi.grib_set_double_array(grib, "values", data.flatten())
示例#8
0
def data_section(cube, grib):
    # Masked data?
    if isinstance(cube.data, ma.core.MaskedArray):
        # What missing value shall we use?
        if not np.isnan(cube.data.fill_value):
            # Use the data's fill value.
            fill_value = float(cube.data.fill_value)
        else:
            # We can't use the data's fill value if it's NaN,
            # the GRIB API doesn't like it.
            # Calculate an MDI outside the data range.
            min, max = cube.data.min(), cube.data.max()
            fill_value = min - (max - min) * 0.1
        # Prepare the unmaksed data array, using fill_value as the MDI.
        data = cube.data.filled(fill_value)
    else:
        fill_value = None
        data = cube.data

    # units scaling
    grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name,
                                              cube.long_name)
    if grib2_info is None:
        # for now, just allow this
        warnings.warn('Unable to determine Grib2 parameter code for cube.\n'
                      'Message data may not be correctly scaled.')
    else:
        if cube.units != grib2_info.units:
            data = cube.units.convert(data, grib2_info.units)
            if fill_value is not None:
                fill_value = cube.units.convert(fill_value, grib2_info.units)

    if fill_value is None:
        # Disable missing values in the grib message.
        gribapi.grib_set(grib, "bitmapPresent", 0)
    else:
        # Enable missing values in the grib message.
        gribapi.grib_set(grib, "bitmapPresent", 1)
        gribapi.grib_set_double(grib, "missingValue", fill_value)
    gribapi.grib_set_double_array(grib, "values", data.flatten())
示例#9
0
def data(cube, grib):
    # mdi
    if isinstance(cube.data, ma.core.MaskedArray):
        gribapi.grib_set(grib, "bitmapPresent", 1)
        gribapi.grib_set_double(grib, "missingValue",
                                float(cube.data.fill_value))
        data = cube.data.filled()
    else:
        gribapi.grib_set_double(grib, "missingValue", float(-1e9))
        data = cube.data

    # units scaling
    grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name,
                                              cube.long_name)
    if grib2_info is None:
        # for now, just allow this
        warnings.warn('Unable to determine Grib2 parameter code for cube.\n'
                      'Message data may not be correctly scaled.')
    else:
        if cube.units != grib2_info.units:
            data = cube.units.convert(data, grib2_info.units)

    # values
    gribapi.grib_set_double_array(grib, "values", data.flatten())
示例#10
0
def data(cube, grib):
    # mdi
    if isinstance(cube.data, ma.core.MaskedArray):
        gribapi.grib_set(grib, "bitmapPresent", 1)
        gribapi.grib_set_double(grib, "missingValue",
                                float(cube.data.fill_value))
        data = cube.data.filled()
    else:
        gribapi.grib_set_double(grib, "missingValue", float(-1e9))
        data = cube.data

    # units scaling
    grib2_info = gptx.cf_phenom_to_grib2_info(cube.standard_name,
                                              cube.long_name)
    if grib2_info is None:
        # for now, just allow this
        warnings.warn('Unable to determine Grib2 parameter code for cube.\n'
                      'Message data may not be correctly scaled.')
    else:
        if cube.units != grib2_info.units:
            data = cube.units.convert(data, grib2_info.units)

    # values
    gribapi.grib_set_double_array(grib, "values", data.flatten())
示例#11
0
def _regularise(grib_message):
    """
    Transform a reduced grid to a regular grid using interpolation.

    Uses 1d linear interpolation at constant latitude to make the grid
    regular. If the longitude dimension is circular then this is taken
    into account by the interpolation. If the longitude dimension is not
    circular then extrapolation is allowed to make sure all end regular
    grid points get a value. In practice this extrapolation is likely to
    be minimal.

    """
    # Make sure to read any missing values as NaN.
    gribapi.grib_set_double(grib_message, "missingValue", np.nan)

    # Get full longitude values, these describe the longitude value of
    # *every* point in the grid, they are not 1d monotonic coordinates.
    lons = gribapi.grib_get_double_array(grib_message, "longitudes")

    # Compute the new longitude coordinate for the regular grid.
    new_nx = max(gribapi.grib_get_long_array(grib_message, "pl"))
    new_x_step = (max(lons) - min(lons)) / (new_nx - 1)
    if gribapi.grib_get_long(grib_message, "iScansNegatively"):
        new_x_step *= -1

    new_lons = np.arange(new_nx) * new_x_step + lons[0]
    # Get full latitude and data values, these describe the latitude and
    # data values of *every* point in the grid, they are not 1d monotonic
    # coordinates.
    lats = gribapi.grib_get_double_array(grib_message, "latitudes")
    values = gribapi.grib_get_double_array(grib_message, "values")

    # Retrieve the distinct latitudes from the GRIB message. GRIBAPI docs
    # don't specify if these points are guaranteed to be oriented correctly so
    # the safe option is to sort them into ascending (south-to-north) order
    # and then reverse the order if necessary.
    new_lats = gribapi.grib_get_double_array(grib_message, "distinctLatitudes")
    new_lats.sort()
    if not gribapi.grib_get_long(grib_message, "jScansPositively"):
        new_lats = new_lats[::-1]
    ny = new_lats.shape[0]

    # Use 1d linear interpolation along latitude circles to regularise the
    # reduced data.
    cyclic = _longitude_is_cyclic(new_lons)
    new_values = np.empty([ny, new_nx], dtype=values.dtype)
    for ilat, lat in enumerate(new_lats):
        idx = np.where(lats == lat)
        llons = lons[idx]
        vvalues = values[idx]
        if cyclic:
            # For cyclic data we insert dummy points at each end to ensure
            # we can interpolate to all output longitudes using pure
            # interpolation.
            cgap = (360 - llons[-1] - llons[0])
            llons = np.concatenate(
                (llons[0:1] - cgap, llons, llons[-1:] + cgap))
            vvalues = np.concatenate(
                (vvalues[-1:], vvalues, vvalues[0:1]))
            fixed_latitude_interpolator = scipy.interpolate.interp1d(
                llons, vvalues)
        else:
            # Allow extrapolation for non-cyclic data sets to ensure we can
            # interpolate to all output longitudes.
            fixed_latitude_interpolator = Linear1dExtrapolator(
                scipy.interpolate.interp1d(llons, vvalues))
        new_values[ilat] = fixed_latitude_interpolator(new_lons)
    new_values = new_values.flatten()

    # Set flags for the regularised data.
    if np.isnan(new_values).any():
        # Account for any missing data.
        gribapi.grib_set_double(grib_message, "missingValue", np.inf)
        gribapi.grib_set(grib_message, "bitmapPresent", 1)
        new_values = np.where(np.isnan(new_values), np.inf, new_values)

    gribapi.grib_set_long(grib_message, "Nx", int(new_nx))
    gribapi.grib_set_double(grib_message,
                            "iDirectionIncrementInDegrees", float(new_x_step))
    gribapi.grib_set_double_array(grib_message, "values", new_values)
    gribapi.grib_set_long(grib_message, "jPointsAreConsecutive", 0)
    gribapi.grib_set_long(grib_message, "PLPresent", 0)
示例#12
0
def _regularise(grib_message):
    """
    Transform a reduced grid to a regular grid using interpolation.

    Uses 1d linear interpolation at constant latitude to make the grid
    regular. If the longitude dimension is circular then this is taken
    into account by the interpolation. If the longitude dimension is not
    circular then extrapolation is allowed to make sure all end regular
    grid points get a value. In practice this extrapolation is likely to
    be minimal.

    """
    # Make sure to read any missing values as NaN.
    gribapi.grib_set_double(grib_message, "missingValue", np.nan)

    # Get full longitude values, these describe the longitude value of
    # *every* point in the grid, they are not 1d monotonic coordinates.
    lons = gribapi.grib_get_double_array(grib_message, "longitudes")

    # Compute the new longitude coordinate for the regular grid.
    new_nx = max(gribapi.grib_get_long_array(grib_message, "pl"))
    new_x_step = (max(lons) - min(lons)) / (new_nx - 1)
    if gribapi.grib_get_long(grib_message, "iScansNegatively"):
        new_x_step *= -1

    new_lons = np.arange(new_nx) * new_x_step + lons[0]
    # Get full latitude and data values, these describe the latitude and
    # data values of *every* point in the grid, they are not 1d monotonic
    # coordinates.
    lats = gribapi.grib_get_double_array(grib_message, "latitudes")
    values = gribapi.grib_get_double_array(grib_message, "values")

    # Retrieve the distinct latitudes from the GRIB message. GRIBAPI docs
    # don't specify if these points are guaranteed to be oriented correctly so
    # the safe option is to sort them into ascending (south-to-north) order
    # and then reverse the order if necessary.
    new_lats = gribapi.grib_get_double_array(grib_message, "distinctLatitudes")
    new_lats.sort()
    if not gribapi.grib_get_long(grib_message, "jScansPositively"):
        new_lats = new_lats[::-1]
    ny = new_lats.shape[0]

    # Use 1d linear interpolation along latitude circles to regularise the
    # reduced data.
    cyclic = _longitude_is_cyclic(new_lons)
    new_values = np.empty([ny, new_nx], dtype=values.dtype)
    for ilat, lat in enumerate(new_lats):
        idx = np.where(lats == lat)
        llons = lons[idx]
        vvalues = values[idx]
        if cyclic:
            # For cyclic data we insert dummy points at each end to ensure
            # we can interpolate to all output longitudes using pure
            # interpolation.
            cgap = (360 - llons[-1] - llons[0])
            llons = np.concatenate(
                (llons[0:1] - cgap, llons, llons[-1:] + cgap))
            vvalues = np.concatenate(
                (vvalues[-1:], vvalues, vvalues[0:1]))
            fixed_latitude_interpolator = scipy.interpolate.interp1d(
                llons, vvalues)
        else:
            # Allow extrapolation for non-cyclic data sets to ensure we can
            # interpolate to all output longitudes.
            fixed_latitude_interpolator = Linear1dExtrapolator(
                scipy.interpolate.interp1d(llons, vvalues))
        new_values[ilat] = fixed_latitude_interpolator(new_lons)
    new_values = new_values.flatten()

    # Set flags for the regularised data.
    if np.isnan(new_values).any():
        # Account for any missing data.
        gribapi.grib_set_double(grib_message, "missingValue", np.inf)
        gribapi.grib_set(grib_message, "bitmapPresent", 1)
        new_values = np.where(np.isnan(new_values), np.inf, new_values)

    gribapi.grib_set_long(grib_message, "Nx", int(new_nx))
    gribapi.grib_set_double(grib_message,
                            "iDirectionIncrementInDegrees", float(new_x_step))
    gribapi.grib_set_double_array(grib_message, "values", new_values)
    gribapi.grib_set_long(grib_message, "jPointsAreConsecutive", 0)
    gribapi.grib_set_long(grib_message, "PLPresent", 0)