Exemple #1
0
    def test_grib1_hybrid_height(self):
        gm = gribapi.grib_new_from_samples('regular_gg_ml_grib1')
        gw = GribWrapper(gm)
        results = grib1_convert(gw)

        factory, = results[0]
        self.assertEqual(factory.factory_class,
                         iris.aux_factory.HybridPressureFactory)
        delta, sigma, ref = factory.args
        self.assertEqual(delta, {'long_name': 'level_pressure'})
        self.assertEqual(sigma, {'long_name': 'sigma'})
        self.assertEqual(ref, Reference(name='surface_pressure'))

        ml_ref = iris.coords.CoordDefn('model_level_number', None, None,
                                       cf_units.Unit('1'), {'positive': 'up'},
                                       None, False)
        lp_ref = iris.coords.CoordDefn(None, 'level_pressure', None,
                                       cf_units.Unit('Pa'), {}, None, False)
        s_ref = iris.coords.CoordDefn(None, 'sigma', None, cf_units.Unit('1'),
                                      {}, None, False)

        aux_coord_defns = [coord._as_defn() for coord, dim in results[8]]
        self.assertIn(ml_ref, aux_coord_defns)
        self.assertIn(lp_ref, aux_coord_defns)
        self.assertIn(s_ref, aux_coord_defns)
Exemple #2
0
 def converter(field):
     if field is press_field:
         src = param_cube
         factories = [
             Factory(HybridHeightFactory, [Reference("orography")])
         ]
         references = []
     else:
         src = orog_cube
         factories = []
         references = [ReferenceTarget("orography", None)]
     dim_coords_and_dims = [(coord, src.coord_dims(coord)[0])
                            for coord in src.dim_coords]
     aux_coords_and_dims = [(coord, src.coord_dims(coord))
                            for coord in src.aux_coords]
     return ConversionMetadata(
         factories,
         references,
         src.standard_name,
         src.long_name,
         src.units,
         src.attributes,
         src.cell_methods,
         dim_coords_and_dims,
         aux_coords_and_dims,
     )
    def test_grib1_hybrid_height(self):
        gm = gribapi.grib_new_from_samples('regular_gg_ml_grib1')
        gw = GribWrapper(gm)
        results = grib1_convert(gw)

        factory, = results[0]
        self.assertEqual(factory.factory_class, HybridPressureFactory)
        delta, sigma, ref = factory.args
        self.assertEqual(delta, {'long_name': 'level_pressure'})
        self.assertEqual(sigma, {'long_name': 'sigma'})
        self.assertEqual(ref, Reference(name='surface_pressure'))

        coords_and_dims = results[8]
        coord, = [
            co for co, _ in coords_and_dims
            if co.name() == 'model_level_number'
        ]
        self.assertEqual(coord.units, '1')
        self.assertEqual(coord.attributes['positive'], 'up')
        coord, = [
            co for co, _ in coords_and_dims if co.name() == 'level_pressure'
        ]
        self.assertEqual(coord.units, 'Pa')
        coord, = [co for co, _ in coords_and_dims if co.name() == 'sigma']
        self.assertEqual(coord.units, '1')
Exemple #4
0
    def test_cross_reference(self):
        # Test the creation process for a factory definition which uses
        # a cross-reference.

        param_cube = stock.realistic_4d_no_derived()
        orog_coord = param_cube.coord('surface_altitude')
        param_cube.remove_coord(orog_coord)

        orog_cube = param_cube[0, 0, :, :]
        orog_cube.data = orog_coord.points
        orog_cube.rename('surface_altitude')
        orog_cube.units = orog_coord.units
        orog_cube.attributes = orog_coord.attributes

        # We're going to test for the presence of the hybrid height
        # stuff later, so let's make sure it's not already there!
        assert len(param_cube.aux_factories) == 0
        assert not param_cube.coords('surface_altitude')

        press_field = Mock()
        orog_field = Mock()
        field_generator = lambda filename: [press_field, orog_field]
        # A fake rule set returning:
        #   1) A parameter cube needing an "orography" reference
        #   2) An "orography" cube
        factory = Factory(HybridHeightFactory, [Reference('orography')])
        press_rule_result = RuleResult(param_cube, Mock(), [factory])
        orog_rule_result = RuleResult(orog_cube, Mock(), [])
        rules = Mock()
        rules.result = lambda field: \
            press_rule_result if field is press_field else orog_rule_result
        # A fake cross-reference rule set
        ref = ReferenceTarget('orography', None)
        orog_xref_rule = Mock()
        orog_xref_rule.run_actions = lambda cube, field: (ref, )
        xref_rules = Mock()
        xref_rules.matching_rules = lambda field: \
            [orog_xref_rule] if field is orog_field else []
        # Finish by making a fake Loader
        name = 'FAKE_PP'
        fake_loader = Loader(field_generator, {}, rules, xref_rules, name)
        cubes = load_cubes(['fake_filename'], None, fake_loader)
        # Check the result is a generator containing both of our cubes.
        self.assertIsInstance(cubes, types.GeneratorType)
        cubes = list(cubes)
        self.assertEqual(len(cubes), 2)
        self.assertIs(cubes[0], orog_cube)
        self.assertIs(cubes[1], param_cube)
        # Check the "cube" has an "aux_factory" added, which itself
        # must have been created with the correct arguments.
        self.assertEqual(len(param_cube.aux_factories), 1)
        self.assertEqual(len(param_cube.coords('surface_altitude')), 1)
Exemple #5
0
def convert(grib):
    """
    Converts a GRIB message into the corresponding items of Cube metadata.

    Args:

    * grib:
        A :class:`~iris.fileformats.grib.GribWrapper` object.

    Returns:
        A :class:`iris.fileformats.rules.ConversionMetadata` object.

    """
    factories = []
    references = []
    standard_name = None
    long_name = None
    units = None
    attributes = {}
    cell_methods = []
    dim_coords_and_dims = []
    aux_coords_and_dims = []

    # deprecation warning for this code path for edition 2 messages
    if grib.edition == 2:
        msg = ('This GRIB loader is deprecated and will be removed in '
               'a future release.  Please consider using the new '
               'GRIB loader by setting the :class:`iris.Future` '
               'option `strict_grib_load` to True; e.g.:\n'
               'iris.FUTURE.strict_grib_load = True\n'
               'Please report issues you experience to:\n'
               'https://groups.google.com/forum/#!topic/scitools-iris-dev/'
               'lMsOusKNfaU')
        warn_deprecated(msg)

    if \
            (grib.gridType=="reduced_gg"):
        aux_coords_and_dims.append(
            (AuxCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        aux_coords_and_dims.append(
            (AuxCoord(grib._x_points,
                      grib._x_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if grib.gridType in ["polar_stereographic", "lambert"]:
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units="m",
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append(
            (DimCoord(grib._x_points,
                      grib._x_coord_name,
                      units="m",
                      coord_system=grib._coord_system), 1))

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 11) and \
            (grib._cf_data is None):
        standard_name = "air_temperature"
        units = "kelvin"

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 33) and \
            (grib._cf_data is None):
        standard_name = "x_wind"
        units = "m s-1"

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 34) and \
            (grib._cf_data is None):
        standard_name = "y_wind"
        units = "m s-1"

    if \
            (grib.edition == 1) and \
            (grib._cf_data is not None):
        standard_name = grib._cf_data.standard_name
        long_name = grib._cf_data.standard_name or grib._cf_data.long_name
        units = grib._cf_data.units

    if \
            (grib.edition == 1) and \
            (grib.table2Version >= 128) and \
            (grib._cf_data is None):
        long_name = "UNKNOWN LOCAL PARAM " + str(
            grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib.edition == 1) and \
            (grib.table2Version == 1) and \
            (grib.indicatorOfParameter >= 128):
        long_name = "UNKNOWN LOCAL PARAM " + str(
            grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib.edition == 2) and \
            (grib._cf_data is not None):
        standard_name = grib._cf_data.standard_name
        long_name = grib._cf_data.long_name
        units = grib._cf_data.units

    if \
            (grib.edition == 1) and \
            (grib._phenomenonDateTime != -1.0):
        aux_coords_and_dims.append(
            (DimCoord(points=grib.startStep,
                      standard_name='forecast_period',
                      units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append(
            (DimCoord(points=grib.phenomenon_points('hours'),
                      standard_name='time',
                      units=Unit('hours since epoch',
                                 CALENDAR_GREGORIAN)), None))

    def add_bounded_time_coords(aux_coords_and_dims, grib):
        t_bounds = grib.phenomenon_bounds('hours')
        period = Unit('hours').convert(t_bounds[1] - t_bounds[0],
                                       grib._forecastTimeUnit)
        aux_coords_and_dims.append(
            (DimCoord(standard_name='forecast_period',
                      units=grib._forecastTimeUnit,
                      points=grib._forecastTime + 0.5 * period,
                      bounds=[grib._forecastTime,
                              grib._forecastTime + period]), None))
        aux_coords_and_dims.append(
            (DimCoord(standard_name='time',
                      units=Unit('hours since epoch', CALENDAR_GREGORIAN),
                      points=0.5 * (t_bounds[0] + t_bounds[1]),
                      bounds=t_bounds), None))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 2):
        add_bounded_time_coords(aux_coords_and_dims, grib)

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 3):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 4):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 5):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 51):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 113):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 114):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 115):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 116):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 117):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 118):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("_covariance", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 123):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 124):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 125):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("standard_deviation", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 0):
        aux_coords_and_dims.append(
            (DimCoord(points=Unit(grib._forecastTimeUnit).convert(
                np.int32(grib._forecastTime), "hours"),
                      standard_name='forecast_period',
                      units="hours"), None))
        aux_coords_and_dims.append(
            (DimCoord(points=grib.phenomenon_points('hours'),
                      standard_name='time',
                      units=Unit('hours since epoch',
                                 CALENDAR_GREGORIAN)), None))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber in (8, 9)):
        add_bounded_time_coords(aux_coords_and_dims, grib)

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 0):
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 1):
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 2):
        cell_methods.append(CellMethod("maximum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 3):
        cell_methods.append(CellMethod("minimum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 4):
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 5):
        cell_methods.append(CellMethod("_root_mean_square", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 6):
        cell_methods.append(CellMethod("standard_deviation", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 7):
        cell_methods.append(CellMethod("_convariance", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 8):
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 9):
        cell_methods.append(CellMethod("_ratio", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.levelType == 'pl'):
        aux_coords_and_dims.append((DimCoord(points=grib.level,
                                             long_name="pressure",
                                             units="hPa"), None))

    if \
            (grib.edition == 1) and \
            (grib.levelType == 'sfc'):

        if (grib._cf_data is not None) and \
        (grib._cf_data.set_height is not None):
            aux_coords_and_dims.append(
                (DimCoord(points=grib._cf_data.set_height,
                          long_name="height",
                          units="m",
                          attributes={'positive': 'up'}), None))
        elif grib.typeOfLevel == 'heightAboveGround':  # required for NCAR
            aux_coords_and_dims.append((DimCoord(points=grib.level,
                                                 long_name="height",
                                                 units="m",
                                                 attributes={'positive':
                                                             'up'}), None))

    if \
            (grib.edition == 1) and \
            (grib.levelType == 'ml') and \
            (hasattr(grib, 'pv')):
        aux_coords_and_dims.append(
            (AuxCoord(grib.level,
                      standard_name='model_level_number',
                      attributes={'positive': 'up'}), None))
        aux_coords_and_dims.append((DimCoord(grib.pv[grib.level],
                                             long_name='level_pressure',
                                             units='Pa'), None))
        aux_coords_and_dims.append((AuxCoord(
            grib.pv[grib.numberOfCoordinatesValues // 2 + grib.level],
            long_name='sigma'), None))
        factories.append(
            Factory(HybridPressureFactory, [{
                'long_name': 'level_pressure'
            }, {
                'long_name': 'sigma'
            },
                                            Reference('surface_pressure')]))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface != grib.typeOfSecondFixedSurface):
        warnings.warn("Different vertical bound types not yet handled.")

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 103) and \
            (grib.typeOfSecondFixedSurface == 255):
        aux_coords_and_dims.append(
            (DimCoord(points=grib.scaledValueOfFirstFixedSurface /
                      (10.0**grib.scaleFactorOfFirstFixedSurface),
                      standard_name="height",
                      units="m"), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 103) and \
            (grib.typeOfSecondFixedSurface != 255):
        aux_coords_and_dims.append((DimCoord(
            points=0.5 * (grib.scaledValueOfFirstFixedSurface /
                          (10.0**grib.scaleFactorOfFirstFixedSurface) +
                          grib.scaledValueOfSecondFixedSurface /
                          (10.0**grib.scaleFactorOfSecondFixedSurface)),
            standard_name="height",
            units="m",
            bounds=[
                grib.scaledValueOfFirstFixedSurface /
                (10.0**grib.scaleFactorOfFirstFixedSurface),
                grib.scaledValueOfSecondFixedSurface /
                (10.0**grib.scaleFactorOfSecondFixedSurface)
            ]), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 100) and \
            (grib.typeOfSecondFixedSurface == 255):
        aux_coords_and_dims.append(
            (DimCoord(points=grib.scaledValueOfFirstFixedSurface /
                      (10.0**grib.scaleFactorOfFirstFixedSurface),
                      long_name="pressure",
                      units="Pa"), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 100) and \
            (grib.typeOfSecondFixedSurface != 255):
        aux_coords_and_dims.append((DimCoord(
            points=0.5 * (grib.scaledValueOfFirstFixedSurface /
                          (10.0**grib.scaleFactorOfFirstFixedSurface) +
                          grib.scaledValueOfSecondFixedSurface /
                          (10.0**grib.scaleFactorOfSecondFixedSurface)),
            long_name="pressure",
            units="Pa",
            bounds=[
                grib.scaledValueOfFirstFixedSurface /
                (10.0**grib.scaleFactorOfFirstFixedSurface),
                grib.scaledValueOfSecondFixedSurface /
                (10.0**grib.scaleFactorOfSecondFixedSurface)
            ]), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface in [105, 119]) and \
            (grib.numberOfCoordinatesValues > 0):
        aux_coords_and_dims.append(
            (AuxCoord(grib.scaledValueOfFirstFixedSurface,
                      standard_name='model_level_number',
                      attributes={'positive': 'up'}), None))
        aux_coords_and_dims.append(
            (DimCoord(grib.pv[grib.scaledValueOfFirstFixedSurface],
                      long_name='level_pressure',
                      units='Pa'), None))
        aux_coords_and_dims.append(
            (AuxCoord(grib.pv[grib.numberOfCoordinatesValues // 2 +
                              grib.scaledValueOfFirstFixedSurface],
                      long_name='sigma'), None))
        factories.append(
            Factory(HybridPressureFactory,
                    [{
                        'long_name': 'level_pressure'
                    }, {
                        'long_name': 'sigma'
                    },
                     Reference('surface_air_pressure')]))

    if grib._originatingCentre != 'unknown':
        aux_coords_and_dims.append((AuxCoord(points=grib._originatingCentre,
                                             long_name='originating_centre',
                                             units='no_unit'), None))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 1):
        aux_coords_and_dims.append((DimCoord(points=grib.perturbationNumber,
                                             long_name='ensemble_member',
                                             units='no_unit'), None))

    if \
            (grib.edition == 2) and \
            grib.productDefinitionTemplateNumber not in (0, 8):
        attributes["GRIB_LOAD_WARNING"] = (
            "unsupported GRIB%d ProductDefinitionTemplate: #4.%d" %
            (grib.edition, grib.productDefinitionTemplateNumber))

    if \
            (grib.edition == 2) and \
            (grib.centre == 'ecmf') and \
            (grib.discipline == 0) and \
            (grib.parameterCategory == 3) and \
            (grib.parameterNumber == 25) and \
            (grib.typeOfFirstFixedSurface == 105):
        references.append(
            ReferenceTarget(
                'surface_air_pressure', lambda cube: {
                    'standard_name': 'surface_air_pressure',
                    'units': 'Pa',
                    'data': np.exp(cube.data)
                }))

    return ConversionMetadata(factories, references, standard_name, long_name,
                              units, attributes, cell_methods,
                              dim_coords_and_dims, aux_coords_and_dims)
Exemple #6
0
def convert(grib):
    factories = []
    references = []
    standard_name = None
    long_name = None
    units = None
    attributes = {}
    cell_methods = []
    dim_coords_and_dims = []
    aux_coords_and_dims = []

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 1))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units='degrees', coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units='degrees', coord_system=grib._coord_system, circular=grib._x_circular), 0))

    if grib.gridType in ["polar_stereographic", "lambert"]:
        dim_coords_and_dims.append((DimCoord(grib._y_points, grib._y_coord_name, units="m", coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points, grib._x_coord_name, units="m", coord_system=grib._coord_system), 1))

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 11) and \
            (grib._cf_data is None):
        standard_name = "air_temperature"
        units = "kelvin"

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 33) and \
            (grib._cf_data is None):
        standard_name = "x_wind"
        units = "m s-1"

    if \
            (grib.edition == 1) and \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 34) and \
            (grib._cf_data is None):
        standard_name = "y_wind"
        units = "m s-1"

    if \
            (grib.edition == 1) and \
            (grib._cf_data is not None):
        standard_name = grib._cf_data.standard_name
        long_name = grib._cf_data.standard_name or grib._cf_data.long_name
        units = grib._cf_data.units

    if \
            (grib.edition == 1) and \
            (grib.table2Version >= 128) and \
            (grib._cf_data is None):
        long_name = "UNKNOWN LOCAL PARAM " + str(grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib.edition == 1) and \
            (grib.table2Version == 1) and \
            (grib.indicatorOfParameter >= 128):
        long_name = "UNKNOWN LOCAL PARAM " + str(grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib.edition == 2) and \
            (grib._cf_data is not None):
        standard_name = grib._cf_data.standard_name
        long_name = grib._cf_data.long_name
        units = grib._cf_data.units

    if \
            (grib.edition == 1) and \
            (grib._phenomenonDateTime != -1.0):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_points('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 3):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 4):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 5):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 51):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 113):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 114):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 115):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 116):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 117):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 118):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("_covariance", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 123):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 124):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.timeRangeIndicator == 125):
        aux_coords_and_dims.append((DimCoord(points=grib.startStep, standard_name='forecast_period', units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], bounds=grib.phenomenon_bounds('hours'),  standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))
        cell_methods.append(CellMethod("standard_deviation", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 0):
        aux_coords_and_dims.append((DimCoord(points=Unit(grib._forecastTimeUnit).convert(np.int32(grib._forecastTime), "hours"), standard_name='forecast_period', units="hours"), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_points('hours'), standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN)), None))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber in (8, 9)):
        aux_coords_and_dims.append((DimCoord(points=Unit(grib._forecastTimeUnit).convert(np.int32(grib._forecastTime), "hours"), standard_name='forecast_period', units="hours"), None))
        aux_coords_and_dims.append((DimCoord(points=grib.phenomenon_bounds('hours')[0], standard_name='time', units=Unit('hours since epoch', iris.unit.CALENDAR_GREGORIAN), bounds=grib.phenomenon_bounds('hours')), None))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 0):
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 1):
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 2):
        cell_methods.append(CellMethod("maximum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 3):
        cell_methods.append(CellMethod("minimum", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 4):
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 5):
        cell_methods.append(CellMethod("_root_mean_square", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 6):
        cell_methods.append(CellMethod("standard_deviation", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 7):
        cell_methods.append(CellMethod("_convariance", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 8):
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 8) and \
            (grib.typeOfStatisticalProcessing == 9):
        cell_methods.append(CellMethod("_ratio", coords="time"))

    if \
            (grib.edition == 1) and \
            (grib.levelType == 'pl'):
        aux_coords_and_dims.append((DimCoord(points=grib.level,  long_name="pressure", units="hPa"), None))

    if \
            (grib.edition == 1) and \
            (grib.levelType == 'sfc') and \
            (grib._cf_data is not None) and \
            (grib._cf_data.set_height is not None):
        aux_coords_and_dims.append((DimCoord(points=grib._cf_data.set_height,  long_name="height", units="m", attributes={'positive':'up'}), None))


    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface != grib.typeOfSecondFixedSurface):
        warnings.warn("Different vertical bound types not yet handled.")

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 103) and \
            (grib.typeOfSecondFixedSurface == 255):
        aux_coords_and_dims.append((DimCoord(points=grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface), standard_name="height", units="m"), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 103) and \
            (grib.typeOfSecondFixedSurface != 255):
        aux_coords_and_dims.append((DimCoord(points=0.5*(grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) + grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)), standard_name="height", units="m", bounds=[grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) , grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)]), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 100) and \
            (grib.typeOfSecondFixedSurface == 255):
        aux_coords_and_dims.append((DimCoord(points=grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface), long_name="pressure", units="Pa"), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface == 100) and \
            (grib.typeOfSecondFixedSurface != 255):
        aux_coords_and_dims.append((DimCoord(points=0.5*(grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) + grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)), long_name="pressure", units="Pa", bounds=[grib.scaledValueOfFirstFixedSurface/(10.0**grib.scaleFactorOfFirstFixedSurface) , grib.scaledValueOfSecondFixedSurface/(10.0**grib.scaleFactorOfSecondFixedSurface)]), None))

    if \
            (grib.edition == 2) and \
            (grib.typeOfFirstFixedSurface in [105, 119]) and \
            (grib.numberOfCoordinatesValues > 0):
        aux_coords_and_dims.append((AuxCoord(grib.scaledValueOfFirstFixedSurface, standard_name='model_level_number', attributes={'positive': 'up'}), None))
        aux_coords_and_dims.append((DimCoord(grib.pv[grib.scaledValueOfFirstFixedSurface], long_name='level_pressure', units='Pa'), None))
        aux_coords_and_dims.append((AuxCoord(grib.pv[grib.numberOfCoordinatesValues/2 + grib.scaledValueOfFirstFixedSurface], long_name='sigma'), None))
        factories.append(Factory(HybridPressureFactory, [{'long_name': 'level_pressure'}, {'long_name': 'sigma'}, Reference('surface_pressure')]))

    if grib._originatingCentre != 'unknown':
        aux_coords_and_dims.append((AuxCoord(points=grib._originatingCentre, long_name='originating_centre', units='no_unit'), None))

    if \
            (grib.edition == 2) and \
            (grib.productDefinitionTemplateNumber == 1):
        aux_coords_and_dims.append((DimCoord(points=grib.perturbationNumber, long_name='ensemble_member', units='no_unit'), None))

    if grib.productDefinitionTemplateNumber not in (0, 8):
        attributes["GRIB_LOAD_WARNING"] = ("unsupported GRIB%d ProductDefinitionTemplate: #4.%d" % (grib.edition, grib.productDefinitionTemplateNumber))

    if \
            (grib.edition == 2) and \
            (grib.centre == 'ecmf') and \
            (grib.discipline == 0) and \
            (grib.parameterCategory == 3) and \
            (grib.parameterNumber == 25) and \
            (grib.typeOfFirstFixedSurface == 105):
        references.append(ReferenceTarget('surface_pressure', lambda cube: {'standard_name': 'surface_air_pressure', 'units': 'Pa', 'data': np.exp(cube.data)}))

    return (factories, references, standard_name, long_name, units, attributes,
            cell_methods, dim_coords_and_dims, aux_coords_and_dims)
Exemple #7
0
def convert(f):
    factories = []
    references = []
    standard_name = None
    long_name = None
    units = None
    attributes = {}
    cell_methods = []
    dim_coords_and_dims = []
    aux_coords_and_dims = []

    if \
            (f.lbtim.ia == 0) and \
            (f.lbtim.ib == 0) and \
            (f.lbtim.ic in [1, 2, 3, 4]) and \
            (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])):
        aux_coords_and_dims.append(
            (DimCoord(f.time_unit('hours').date2num(f.t1),
                      standard_name='time',
                      units=f.time_unit('hours')), None))

    if \
            (f.lbtim.ia == 0) and \
            (f.lbtim.ib == 1) and \
            (f.lbtim.ic in [1, 2, 3, 4]) and \
            (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])):
        aux_coords_and_dims.append((DimCoord(f.time_unit('hours',
                                                         f.t2).date2num(f.t1),
                                             standard_name='forecast_period',
                                             units='hours'), None))
        aux_coords_and_dims.append(
            (DimCoord(f.time_unit('hours').date2num(f.t1),
                      standard_name='time',
                      units=f.time_unit('hours')), None))
        aux_coords_and_dims.append(
            (DimCoord(f.time_unit('hours').date2num(f.t2),
                      standard_name='forecast_reference_time',
                      units=f.time_unit('hours')), None))

    if \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])):
        t_unit = f.time_unit('hours')
        t1_hours = t_unit.date2num(f.t1)
        t2_hours = t_unit.date2num(f.t2)
        period = t2_hours - t1_hours
        aux_coords_and_dims.append((DimCoord(standard_name='forecast_period',
                                             units='hours',
                                             points=f.lbft - 0.5 * period,
                                             bounds=[f.lbft - period,
                                                     f.lbft]), None))
        aux_coords_and_dims.append(
            (DimCoord(standard_name='time',
                      units=t_unit,
                      points=0.5 * (t1_hours + t2_hours),
                      bounds=[t1_hours, t2_hours]), None))
        aux_coords_and_dims.append(
            (DimCoord(f.time_unit('hours').date2num(f.t2) - f.lbft,
                      standard_name='forecast_reference_time',
                      units=f.time_unit('hours')), None))

    if \
            (f.lbtim.ib == 3) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])):
        t_unit = f.time_unit('hours')
        t1_hours = t_unit.date2num(f.t1)
        t2_hours = t_unit.date2num(f.t2)
        period = t2_hours - t1_hours
        aux_coords_and_dims.append((DimCoord(standard_name='forecast_period',
                                             units='hours',
                                             points=f.lbft,
                                             bounds=[f.lbft - period,
                                                     f.lbft]), None))
        aux_coords_and_dims.append((DimCoord(standard_name='time',
                                             units=t_unit,
                                             points=t2_hours,
                                             bounds=[t1_hours,
                                                     t2_hours]), None))
        aux_coords_and_dims.append(
            (DimCoord(f.time_unit('hours').date2num(f.t2) - f.lbft,
                      standard_name='forecast_reference_time',
                      units=f.time_unit('hours')), None))

    if \
            (f.lbtim.ib == 3) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \
            (f.lbmon == 12 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \
            (f.lbmond == 3 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0):
        aux_coords_and_dims.append((AuxCoord('djf',
                                             long_name='season',
                                             units='no_unit'), None))

    if \
            (f.lbtim.ib == 3) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \
            (f.lbmon == 3 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \
            (f.lbmond == 6 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0):
        aux_coords_and_dims.append((AuxCoord('mam',
                                             long_name='season',
                                             units='no_unit'), None))

    if \
            (f.lbtim.ib == 3) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \
            (f.lbmon == 6 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \
            (f.lbmond == 9 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0):
        aux_coords_and_dims.append((AuxCoord('jja',
                                             long_name='season',
                                             units='no_unit'), None))

    if \
            (f.lbtim.ib == 3) and \
            (f.lbtim.ic in [1, 2, 4]) and \
            ((len(f.lbcode) != 5) or (len(f.lbcode) == 5 and f.lbcode.ix not in [20, 21, 22, 23] and f.lbcode.iy not in [20, 21, 22, 23])) and \
            (f.lbmon == 9 and f.lbdat == 1 and f.lbhr == 0 and f.lbmin == 0) and \
            (f.lbmond == 12 and f.lbdatd == 1 and f.lbhrd == 0 and f.lbmind == 0):
        aux_coords_and_dims.append((AuxCoord('son',
                                             long_name='season',
                                             units='no_unit'), None))

    if \
            (f.bdx != 0.0) and \
            (f.bdx != f.bmdi) and \
            (len(f.lbcode) != 5) and \
            (f.lbcode[0] == 1):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzx,
                                   f.bdx,
                                   f.lbnpt,
                                   standard_name=f._x_coord_name(),
                                   units='degrees',
                                   circular=(f.lbhem in [0, 4]),
                                   coord_system=f.coord_system()), 1))

    if \
            (f.bdx != 0.0) and \
            (f.bdx != f.bmdi) and \
            (len(f.lbcode) != 5) and \
            (f.lbcode[0] == 2):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzx,
                                   f.bdx,
                                   f.lbnpt,
                                   standard_name=f._x_coord_name(),
                                   units='degrees',
                                   circular=(f.lbhem in [0, 4]),
                                   coord_system=f.coord_system(),
                                   with_bounds=True), 1))

    if \
            (f.bdy != 0.0) and \
            (f.bdy != f.bmdi) and \
            (len(f.lbcode) != 5) and \
            (f.lbcode[0] == 1):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzy,
                                   f.bdy,
                                   f.lbrow,
                                   standard_name=f._y_coord_name(),
                                   units='degrees',
                                   coord_system=f.coord_system()), 0))

    if \
            (f.bdy != 0.0) and \
            (f.bdy != f.bmdi) and \
            (len(f.lbcode) != 5) and \
            (f.lbcode[0] == 2):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzy,
                                   f.bdy,
                                   f.lbrow,
                                   standard_name=f._y_coord_name(),
                                   units='degrees',
                                   coord_system=f.coord_system(),
                                   with_bounds=True), 0))

    if \
            (f.bdy == 0.0 or f.bdy == f.bmdi) and \
            (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.iy == 10)):
        dim_coords_and_dims.append(
            (DimCoord(f.y,
                      standard_name=f._y_coord_name(),
                      units='degrees',
                      bounds=f.y_bounds,
                      coord_system=f.coord_system()), 0))

    if \
            (f.bdx == 0.0 or f.bdx == f.bmdi) and \
            (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and f.lbcode.ix == 11)):
        dim_coords_and_dims.append(
            (DimCoord(f.x,
                      standard_name=f._x_coord_name(),
                      units='degrees',
                      bounds=f.x_bounds,
                      circular=(f.lbhem in [0, 4]),
                      coord_system=f.coord_system()), 1))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode.iy == 2) and \
            (f.bdy == 0 or f.bdy == f.bmdi):
        dim_coords_and_dims.append((DimCoord(f.y,
                                             standard_name='height',
                                             units='km',
                                             bounds=f.y_bounds,
                                             attributes={'positive':
                                                         'up'}), 0))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode[-1] == 1) and \
            (f.lbcode.iy == 4):
        dim_coords_and_dims.append((DimCoord(f.y,
                                             standard_name='depth',
                                             units='m',
                                             bounds=f.y_bounds,
                                             attributes={'positive':
                                                         'down'}), 0))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode.ix == 10) and \
            (f.bdx != 0) and \
            (f.bdx != f.bmdi):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzx,
                                   f.bdx,
                                   f.lbnpt,
                                   standard_name=f._y_coord_name(),
                                   units='degrees',
                                   coord_system=f.coord_system()), 1))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode.iy == 1) and \
            (f.bdy == 0 or f.bdy == f.bmdi):
        dim_coords_and_dims.append((DimCoord(f.y,
                                             long_name='pressure',
                                             units='hPa',
                                             bounds=f.y_bounds), 0))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode.ix == 1) and \
            (f.bdx == 0 or f.bdx == f.bmdi):
        dim_coords_and_dims.append((DimCoord(f.x,
                                             long_name='pressure',
                                             units='hPa',
                                             bounds=f.x_bounds), 1))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode[-1] == 1) and \
            (f.lbcode.iy == 23):
        dim_coords_and_dims.append((DimCoord(
            f.y,
            standard_name='time',
            units=iris.unit.Unit('days since 0000-01-01 00:00:00',
                                 calendar=iris.unit.CALENDAR_360_DAY),
            bounds=f.y_bounds), 0))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode[-1] == 1) and \
            (f.lbcode.ix == 23):
        dim_coords_and_dims.append((DimCoord(
            f.x,
            standard_name='time',
            units=iris.unit.Unit('days since 0000-01-01 00:00:00',
                                 calendar=iris.unit.CALENDAR_360_DAY),
            bounds=f.x_bounds), 1))

    if \
            (len(f.lbcode) == 5) and \
            (f.lbcode[-1] == 1) and \
            (f.lbcode.ix == 13) and \
            (f.bdx != 0):
        dim_coords_and_dims.append(
            (DimCoord.from_regular(f.bzx,
                                   f.bdx,
                                   f.lbnpt,
                                   long_name='site_number',
                                   units='1'), 1))

    if \
            (len(f.lbcode) == 5) and \
            (13 in [f.lbcode.ix, f.lbcode.iy]) and \
            (11 not in [f.lbcode.ix, f.lbcode.iy]) and \
            (hasattr(f, 'lower_x_domain')) and \
            (hasattr(f, 'upper_x_domain')) and \
            (all(f.lower_x_domain != -1.e+30)) and \
            (all(f.upper_x_domain != -1.e+30)):
        aux_coords_and_dims.append((AuxCoord(
            (f.lower_x_domain + f.upper_x_domain) / 2.0,
            standard_name=f._x_coord_name(),
            units='degrees',
            bounds=np.array([f.lower_x_domain, f.upper_x_domain]).T,
            coord_system=f.coord_system()), 1 if f.lbcode.ix == 13 else 0))

    if \
            (len(f.lbcode) == 5) and \
            (13 in [f.lbcode.ix, f.lbcode.iy]) and \
            (10 not in [f.lbcode.ix, f.lbcode.iy]) and \
            (hasattr(f, 'lower_y_domain')) and \
            (hasattr(f, 'upper_y_domain')) and \
            (all(f.lower_y_domain != -1.e+30)) and \
            (all(f.upper_y_domain != -1.e+30)):
        aux_coords_and_dims.append((AuxCoord(
            (f.lower_y_domain + f.upper_y_domain) / 2.0,
            standard_name=f._y_coord_name(),
            units='degrees',
            bounds=np.array([f.lower_y_domain, f.upper_y_domain]).T,
            coord_system=f.coord_system()), 1 if f.lbcode.ix == 13 else 0))

    if \
            (f.lbproc == 128) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia == 0):
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (f.lbproc == 128) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia != 0):
        cell_methods.append(
            CellMethod("mean", coords="time",
                       intervals="%d hour" % f.lbtim.ia))

    if \
            (f.lbproc == 128) and \
            (f.lbtim.ib == 3):
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (f.lbproc == 128) and \
            (f.lbtim.ib not in [2, 3]):
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (f.lbproc == 4096) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia == 0):
        cell_methods.append(CellMethod("minimum", coords="time"))

    if \
            (f.lbproc == 4096) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia != 0):
        cell_methods.append(
            CellMethod("minimum",
                       coords="time",
                       intervals="%d hour" % f.lbtim.ia))

    if \
            (f.lbproc == 4096) and \
            (f.lbtim.ib != 2):
        cell_methods.append(CellMethod("minimum", coords="time"))

    if \
            (f.lbproc == 8192) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia == 0):
        cell_methods.append(CellMethod("maximum", coords="time"))

    if \
            (f.lbproc == 8192) and \
            (f.lbtim.ib == 2) and \
            (f.lbtim.ia != 0):
        cell_methods.append(
            CellMethod("maximum",
                       coords="time",
                       intervals="%d hour" % f.lbtim.ia))

    if \
            (f.lbproc == 8192) and \
            (f.lbtim.ib != 2):
        cell_methods.append(CellMethod("maximum", coords="time"))

    if f.lbproc not in [0, 128, 4096, 8192]:
        attributes["ukmo__process_flags"] = tuple(
            sorted([
                iris.fileformats.pp.lbproc_map[flag] for flag in f.lbproc.flags
            ]))

    if \
            (f.lbvc == 1) and \
            (not (str(f.stash) in ['m01s03i236', 'm01s03i237', 'm01s03i245', 'm01s03i247', 'm01s03i250'])) and \
            (f.blev != -1):
        aux_coords_and_dims.append((DimCoord(f.blev,
                                             standard_name='height',
                                             units='m',
                                             attributes={'positive':
                                                         'up'}), None))

    if str(f.stash) in [
            'm01s03i236', 'm01s03i237', 'm01s03i245', 'm01s03i247',
            'm01s03i250'
    ]:
        aux_coords_and_dims.append((DimCoord(1.5,
                                             standard_name='height',
                                             units='m',
                                             attributes={'positive':
                                                         'up'}), None))

    if \
            (len(f.lbcode) != 5) and \
            (f.lbvc == 2):
        aux_coords_and_dims.append(
            (DimCoord(_model_level_number(f),
                      standard_name='model_level_number',
                      attributes={'positive': 'down'}), None))

    if \
            (len(f.lbcode) != 5) and \
            (f.lbvc == 2) and \
            (f.brsvd[0] == f.brlev):
        aux_coords_and_dims.append((DimCoord(f.blev,
                                             standard_name='depth',
                                             units='m',
                                             attributes={'positive':
                                                         'down'}), None))

    if \
            (len(f.lbcode) != 5) and \
            (f.lbvc == 2) and \
            (f.brsvd[0] != f.brlev):
        aux_coords_and_dims.append((DimCoord(f.blev,
                                             standard_name='depth',
                                             units='m',
                                             bounds=[f.brsvd[0], f.brlev],
                                             attributes={'positive':
                                                         'down'}), None))

    # soil level
    if len(f.lbcode) != 5 and f.lbvc == 6:
        aux_coords_and_dims.append(
            (DimCoord(_model_level_number(f),
                      long_name='soil_model_level_number',
                      attributes={'positive': 'down'}), None))

    if \
            (f.lbvc == 8) and \
            (len(f.lbcode) != 5 or (len(f.lbcode) == 5 and 1 not in [f.lbcode.ix, f.lbcode.iy])):
        aux_coords_and_dims.append((DimCoord(f.blev,
                                             long_name='pressure',
                                             units='hPa'), None))

    if \
            (len(f.lbcode) != 5) and \
            (f.lbvc == 19):
        aux_coords_and_dims.append(
            (DimCoord(f.blev,
                      standard_name='air_potential_temperature',
                      units='K',
                      attributes={'positive': 'up'}), None))

    # Hybrid pressure coordinate
    if f.lbvc == 9:
        model_level_number = DimCoord(_model_level_number(f),
                                      standard_name='model_level_number',
                                      attributes={'positive': 'up'})
        # The following match the hybrid height scheme, but data has the
        # blev and bhlev values the other way around.
        #level_pressure = DimCoord(f.blev,
        #                          long_name='level_pressure',
        #                          units='Pa',
        #                          bounds=[f.brlev, f.brsvd[0]])
        #sigma = AuxCoord(f.bhlev,
        #                 long_name='sigma',
        #                 bounds=[f.bhrlev, f.brsvd[1]])
        level_pressure = DimCoord(f.bhlev,
                                  long_name='level_pressure',
                                  units='Pa',
                                  bounds=[f.bhrlev, f.brsvd[1]])
        sigma = AuxCoord(f.blev,
                         long_name='sigma',
                         bounds=[f.brlev, f.brsvd[0]])
        aux_coords_and_dims.extend([(model_level_number, None),
                                    (level_pressure, None), (sigma, None)])
        factories.append(
            Factory(HybridPressureFactory,
                    [{
                        'long_name': 'level_pressure'
                    }, {
                        'long_name': 'sigma'
                    },
                     Reference('surface_air_pressure')]))

    if f.lbvc == 65:
        aux_coords_and_dims.append(
            (DimCoord(_model_level_number(f),
                      standard_name='model_level_number',
                      attributes={'positive': 'up'}), None))
        aux_coords_and_dims.append((DimCoord(f.blev,
                                             long_name='level_height',
                                             units='m',
                                             bounds=[f.brlev, f.brsvd[0]],
                                             attributes={'positive':
                                                         'up'}), None))
        aux_coords_and_dims.append((AuxCoord(f.bhlev,
                                             long_name='sigma',
                                             bounds=[f.bhrlev,
                                                     f.brsvd[1]]), None))
        factories.append(
            Factory(HybridHeightFactory, [{
                'long_name': 'level_height'
            }, {
                'long_name': 'sigma'
            },
                                          Reference('orography')]))

    if f.lbrsvd[3] != 0:
        aux_coords_and_dims.append(
            (DimCoord(f.lbrsvd[3], standard_name='realization'), None))

    if f.lbuser[4] != 0:
        aux_coords_and_dims.append((DimCoord(f.lbuser[4],
                                             long_name='pseudo_level',
                                             units='1'), None))

    if f.lbuser[6] == 1 and f.lbuser[3] == 5226:
        standard_name = "precipitation_amount"
        units = "kg m-2"

    if \
            (f.lbuser[6] == 2) and \
            (f.lbuser[3] == 101):
        standard_name = "sea_water_potential_temperature"
        units = "Celsius"

    if \
            ((f.lbsrce % 10000) == 1111) and \
            ((f.lbsrce / 10000) / 100.0 > 0):
        attributes['source'] = 'Data from Met Office Unified Model %4.2f' % (
            (f.lbsrce / 10000) / 100.0)

    if \
            ((f.lbsrce % 10000) == 1111) and \
            ((f.lbsrce / 10000) / 100.0 == 0):
        attributes['source'] = 'Data from Met Office Unified Model'

    if f.lbuser[6] != 0 or (f.lbuser[3] / 1000) != 0 or (f.lbuser[3] %
                                                         1000) != 0:
        attributes['STASH'] = f.stash

    if \
            (f.lbuser[6] == 1) and \
            (f.lbuser[3] == 4205):
        standard_name = "mass_fraction_of_cloud_ice_in_air"
        units = "1"

    if \
            (f.lbuser[6] == 1) and \
            (f.lbuser[3] == 4206):
        standard_name = "mass_fraction_of_cloud_liquid_water_in_air"
        units = "1"

    if \
            (f.lbuser[6] == 1) and \
            (f.lbuser[3] == 30204):
        standard_name = "air_temperature"
        units = "K"

    if \
            (f.lbuser[6] == 4) and \
            (f.lbuser[3] == 6001):
        standard_name = "sea_surface_wave_significant_height"
        units = "m"

    if str(f.stash) in STASH_TO_CF:
        standard_name = STASH_TO_CF[str(f.stash)].standard_name
        units = STASH_TO_CF[str(f.stash)].units
        long_name = STASH_TO_CF[str(f.stash)].long_name

    if \
            (not f.stash.is_valid) and \
            (f.lbfc in LBFC_TO_CF):
        standard_name = LBFC_TO_CF[f.lbfc].standard_name
        units = LBFC_TO_CF[f.lbfc].units
        long_name = LBFC_TO_CF[f.lbfc].long_name

    if f.lbuser[3] == 33:
        references.append(ReferenceTarget('orography', None))

    if f.lbuser[3] == 409 or f.lbuser[3] == 1:
        references.append(ReferenceTarget('surface_air_pressure', None))

    return (factories, references, standard_name, long_name, units, attributes,
            cell_methods, dim_coords_and_dims, aux_coords_and_dims)
Exemple #8
0
def _convert_vertical_coords(lbcode,
                             lbvc,
                             blev,
                             lblev,
                             stash,
                             bhlev,
                             bhrlev,
                             brsvd1,
                             brsvd2,
                             brlev,
                             dim=None):
    """
    Encode scalar or vector vertical level values from PP headers as CM data
    components.

    Args:

    * lbcode:
        Scalar field :class:`iris.fileformats.pp.SplittableInt` value.

    * lbvc:
        Scalar field value.

    * blev:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * lblev:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * stash:
        Scalar field :class:`iris.fileformats.pp.STASH` value.

    * bhlev:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * bhrlev:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * brsvd1:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * brsvd2:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    * brlev:
        Scalar field value or :class:`numpy.ndarray` vector of field values.

    Kwargs:

    * dim:
        Associated dimension of the vertical coordinate. Defaults to None.

    Returns:
        A tuple containing a list of coords_and_dims, and a list of factories.

    """
    factories = []
    coords_and_dims = []

    # See Word no. 33 (LBLEV) in section 4 of UM Model Docs (F3).
    BASE_RHO_LEVEL_LBLEV = 9999
    model_level_number = np.atleast_1d(lblev)
    model_level_number[model_level_number == BASE_RHO_LEVEL_LBLEV] = 0

    # Ensure to vectorise these arguments as arrays, as they participate
    # in the conditions of convert rules.
    blev = np.atleast_1d(blev)
    brsvd1 = np.atleast_1d(brsvd1)
    brlev = np.atleast_1d(brlev)

    # Height.
    if (lbvc == 1) and \
            str(stash) not in STASHCODE_IMPLIED_HEIGHTS and \
            np.all(blev != -1):
        coord = _dim_or_aux(blev,
                            standard_name='height',
                            units='m',
                            attributes={'positive': 'up'})
        coords_and_dims.append((coord, dim))

    if str(stash) in STASHCODE_IMPLIED_HEIGHTS:
        height = STASHCODE_IMPLIED_HEIGHTS[str(stash)]
        coord = DimCoord(height,
                         standard_name='height',
                         units='m',
                         attributes={'positive': 'up'})
        coords_and_dims.append((coord, None))

    # Model level number.
    if (len(lbcode) != 5) and \
            (lbvc == 2):
        coord = _dim_or_aux(model_level_number,
                            standard_name='model_level_number',
                            attributes={'positive': 'down'})
        coords_and_dims.append((coord, dim))

    # Depth - unbound.
    if (len(lbcode) != 5) and \
            (lbvc == 2) and \
            np.all(brsvd1 == brlev):
        coord = _dim_or_aux(blev,
                            standard_name='depth',
                            units='m',
                            attributes={'positive': 'down'})
        coords_and_dims.append((coord, dim))

    # Depth - bound.
    if (len(lbcode) != 5) and \
            (lbvc == 2) and \
            np.all(brsvd1 != brlev):
        coord = _dim_or_aux(blev,
                            standard_name='depth',
                            units='m',
                            bounds=np.vstack((brsvd1, brlev)).T,
                            attributes={'positive': 'down'})
        coords_and_dims.append((coord, dim))

    # Depth - unbound and bound (mixed).
    if (len(lbcode) != 5) and \
            (lbvc == 2) and \
            (np.any(brsvd1 == brlev) and np.any(brsvd1 != brlev)):
        lower = np.where(brsvd1 == brlev, blev, brsvd1)
        upper = np.where(brsvd1 == brlev, blev, brlev)
        coord = _dim_or_aux(blev,
                            standard_name='depth',
                            units='m',
                            bounds=np.vstack((lower, upper)).T,
                            attributes={'positive': 'down'})
        coords_and_dims.append((coord, dim))

    # Soil level/depth.
    if len(lbcode) != 5 and lbvc == 6:
        if np.all(brsvd1 == 0) and np.all(brlev == 0):
            # UM populates lblev, brsvd1 and brlev metadata INCORRECTLY,
            # so continue to treat as a soil level.
            coord = _dim_or_aux(model_level_number,
                                long_name='soil_model_level_number',
                                attributes={'positive': 'down'})
            coords_and_dims.append((coord, dim))
        elif np.any(brsvd1 != brlev):
            # UM populates metadata CORRECTLY,
            # so treat it as the expected (bounded) soil depth.
            coord = _dim_or_aux(blev,
                                standard_name='depth',
                                units='m',
                                bounds=np.vstack((brsvd1, brlev)).T,
                                attributes={'positive': 'down'})
            coords_and_dims.append((coord, dim))

    # Pressure.
    if (lbvc == 8) and \
            (len(lbcode) != 5 or (len(lbcode) == 5 and
                                  1 not in [lbcode.ix, lbcode.iy])):
        coord = _dim_or_aux(blev, long_name='pressure', units='hPa')
        coords_and_dims.append((coord, dim))

    # Air potential temperature.
    if (len(lbcode) != 5) and \
            (lbvc == 19):
        coord = _dim_or_aux(blev,
                            standard_name='air_potential_temperature',
                            units='K',
                            attributes={'positive': 'up'})
        coords_and_dims.append((coord, dim))

    # Hybrid pressure levels.
    if lbvc == 9:
        model_level_number = _dim_or_aux(model_level_number,
                                         standard_name='model_level_number',
                                         attributes={'positive': 'up'})
        level_pressure = _dim_or_aux(bhlev,
                                     long_name='level_pressure',
                                     units='Pa',
                                     bounds=np.vstack((bhrlev, brsvd2)).T)
        sigma = AuxCoord(blev,
                         long_name='sigma',
                         bounds=np.vstack((brlev, brsvd1)).T)
        coords_and_dims.extend([(model_level_number, dim),
                                (level_pressure, dim), (sigma, dim)])
        factories.append(
            Factory(HybridPressureFactory,
                    [{
                        'long_name': 'level_pressure'
                    }, {
                        'long_name': 'sigma'
                    },
                     Reference('surface_air_pressure')]))

    # Hybrid height levels.
    if lbvc == 65:
        model_level_number = _dim_or_aux(model_level_number,
                                         standard_name='model_level_number',
                                         attributes={'positive': 'up'})
        level_height = _dim_or_aux(blev,
                                   long_name='level_height',
                                   units='m',
                                   bounds=np.vstack((brlev, brsvd1)).T,
                                   attributes={'positive': 'up'})
        sigma = AuxCoord(bhlev,
                         long_name='sigma',
                         bounds=np.vstack((bhrlev, brsvd2)).T)
        coords_and_dims.extend([(model_level_number, dim), (level_height, dim),
                                (sigma, dim)])
        factories.append(
            Factory(HybridHeightFactory, [{
                'long_name': 'level_height'
            }, {
                'long_name': 'sigma'
            },
                                          Reference('orography')]))

    return coords_and_dims, factories
Exemple #9
0
def grib1_convert(grib):
    """
    Converts a GRIB1 message into the corresponding items of Cube metadata.

    Args:

    * grib:
        A :class:`~iris_grib.GribWrapper` object.

    Returns:
        A :class:`iris.fileformats.rules.ConversionMetadata` object.

    """
    if grib.edition != 1:
        emsg = 'GRIB edition {} is not supported by {!r}.'
        raise TranslationError(emsg.format(grib.edition, type(grib).__name__))

    factories = []
    references = []
    standard_name = None
    long_name = None
    units = None
    attributes = {}
    cell_methods = []
    dim_coords_and_dims = []
    aux_coords_and_dims = []

    if \
            (grib.gridType=="reduced_gg"):
        aux_coords_and_dims.append(
            (AuxCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        aux_coords_and_dims.append(
            (AuxCoord(grib._x_points,
                      grib._x_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="regular_gg") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 0):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 1))

    if \
            (grib.gridType=="rotated_ll") and \
            (grib.jPointsAreConsecutive == 1):
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units='degrees',
                      coord_system=grib._coord_system), 1))
        dim_coords_and_dims.append((DimCoord(grib._x_points,
                                             grib._x_coord_name,
                                             units='degrees',
                                             coord_system=grib._coord_system,
                                             circular=grib._x_circular), 0))

    if grib.gridType in ["polar_stereographic", "lambert"]:
        dim_coords_and_dims.append(
            (DimCoord(grib._y_points,
                      grib._y_coord_name,
                      units="m",
                      coord_system=grib._coord_system), 0))
        dim_coords_and_dims.append(
            (DimCoord(grib._x_points,
                      grib._x_coord_name,
                      units="m",
                      coord_system=grib._coord_system), 1))

    if \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 11) and \
            (grib._cf_data is None):
        standard_name = "air_temperature"
        units = "kelvin"

    if \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 33) and \
            (grib._cf_data is None):
        standard_name = "x_wind"
        units = "m s-1"

    if \
            (grib.table2Version < 128) and \
            (grib.indicatorOfParameter == 34) and \
            (grib._cf_data is None):
        standard_name = "y_wind"
        units = "m s-1"

    if \
            (grib._cf_data is not None):
        standard_name = grib._cf_data.standard_name
        long_name = grib._cf_data.standard_name or grib._cf_data.long_name
        units = grib._cf_data.units

    if \
            (grib.table2Version >= 128) and \
            (grib._cf_data is None):
        long_name = "UNKNOWN LOCAL PARAM " + str(
            grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib.table2Version == 1) and \
            (grib.indicatorOfParameter >= 128):
        long_name = "UNKNOWN LOCAL PARAM " + str(
            grib.indicatorOfParameter) + "." + str(grib.table2Version)
        units = "???"

    if \
            (grib._phenomenonDateTime != -1.0):
        aux_coords_and_dims.append(
            (DimCoord(points=grib.startStep,
                      standard_name='forecast_period',
                      units=grib._forecastTimeUnit), None))
        aux_coords_and_dims.append(
            (DimCoord(points=grib.phenomenon_points('hours'),
                      standard_name='time',
                      units=Unit('hours since epoch',
                                 CALENDAR_GREGORIAN)), None))

    def add_bounded_time_coords(aux_coords_and_dims, grib):
        t_bounds = grib.phenomenon_bounds('hours')
        period = Unit('hours').convert(t_bounds[1] - t_bounds[0],
                                       grib._forecastTimeUnit)
        aux_coords_and_dims.append(
            (DimCoord(standard_name='forecast_period',
                      units=grib._forecastTimeUnit,
                      points=grib._forecastTime + 0.5 * period,
                      bounds=[grib._forecastTime,
                              grib._forecastTime + period]), None))
        aux_coords_and_dims.append(
            (DimCoord(standard_name='time',
                      units=Unit('hours since epoch', CALENDAR_GREGORIAN),
                      points=0.5 * (t_bounds[0] + t_bounds[1]),
                      bounds=t_bounds), None))

    if \
            (grib.timeRangeIndicator == 2):
        add_bounded_time_coords(aux_coords_and_dims, grib)

    if \
            (grib.timeRangeIndicator == 3):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 4):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.timeRangeIndicator == 5):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("_difference", coords="time"))

    if \
            (grib.timeRangeIndicator == 51):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 113):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 114):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.timeRangeIndicator == 115):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 116):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.timeRangeIndicator == 117):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 118):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("_covariance", coords="time"))

    if \
            (grib.timeRangeIndicator == 123):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("mean", coords="time"))

    if \
            (grib.timeRangeIndicator == 124):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("sum", coords="time"))

    if \
            (grib.timeRangeIndicator == 125):
        add_bounded_time_coords(aux_coords_and_dims, grib)
        cell_methods.append(CellMethod("standard_deviation", coords="time"))

    if \
            (grib.levelType == 'pl'):
        aux_coords_and_dims.append((DimCoord(points=grib.level,
                                             long_name="pressure",
                                             units="hPa"), None))

    if \
            (grib.levelType == 'sfc'):

        if (grib._cf_data is not None) and \
        (grib._cf_data.set_height is not None):
            aux_coords_and_dims.append(
                (DimCoord(points=grib._cf_data.set_height,
                          long_name="height",
                          units="m",
                          attributes={'positive': 'up'}), None))
        elif grib.typeOfLevel == 'heightAboveGround':  # required for NCAR
            aux_coords_and_dims.append((DimCoord(points=grib.level,
                                                 long_name="height",
                                                 units="m",
                                                 attributes={'positive':
                                                             'up'}), None))

    if \
            (grib.levelType == 'ml') and \
            (hasattr(grib, 'pv')):
        aux_coords_and_dims.append(
            (AuxCoord(grib.level,
                      standard_name='model_level_number',
                      units=1,
                      attributes={'positive': 'up'}), None))
        aux_coords_and_dims.append((DimCoord(grib.pv[grib.level],
                                             long_name='level_pressure',
                                             units='Pa'), None))
        aux_coords_and_dims.append((AuxCoord(
            grib.pv[grib.numberOfCoordinatesValues // 2 + grib.level],
            long_name='sigma',
            units=1), None))
        factories.append(
            Factory(HybridPressureFactory, [{
                'long_name': 'level_pressure'
            }, {
                'long_name': 'sigma'
            },
                                            Reference('surface_pressure')]))

    if grib._originatingCentre != 'unknown':
        aux_coords_and_dims.append((AuxCoord(points=grib._originatingCentre,
                                             long_name='originating_centre',
                                             units='no_unit'), None))

    return ConversionMetadata(factories, references, standard_name, long_name,
                              units, attributes, cell_methods,
                              dim_coords_and_dims, aux_coords_and_dims)
Exemple #10
0
def _convert_scalar_vertical_coords(lbcode, lbvc, blev, lblev, stash, bhlev,
                                    bhrlev, brsvd1, brsvd2, brlev):
    """
    Encode scalar vertical level values from PP headers as CM data components.

    Returns (<list of coords_and_dims>, <list of factories>)

    """
    factories = []
    coords_and_dims = []
    model_level_number = _model_level_number(lblev)

    if \
            (lbvc == 1) and \
            (str(stash) not in STASHCODE_IMPLIED_HEIGHTS) and \
            (blev != -1):
        coords_and_dims.append((DimCoord(blev,
                                         standard_name='height',
                                         units='m',
                                         attributes={'positive': 'up'}), None))

    if str(stash) in STASHCODE_IMPLIED_HEIGHTS:
        coords_and_dims.append((DimCoord(STASHCODE_IMPLIED_HEIGHTS[str(stash)],
                                         standard_name='height',
                                         units='m',
                                         attributes={'positive': 'up'}), None))

    if \
            (len(lbcode) != 5) and \
            (lbvc == 2):
        coords_and_dims.append((DimCoord(model_level_number,
                                         standard_name='model_level_number',
                                         attributes={'positive':
                                                     'down'}), None))

    if \
            (len(lbcode) != 5) and \
            (lbvc == 2) and \
            (brsvd1 == brlev):
        coords_and_dims.append((DimCoord(blev,
                                         standard_name='depth',
                                         units='m',
                                         attributes={'positive':
                                                     'down'}), None))

    if \
            (len(lbcode) != 5) and \
            (lbvc == 2) and \
            (brsvd1 != brlev):
        coords_and_dims.append((DimCoord(blev,
                                         standard_name='depth',
                                         units='m',
                                         bounds=[brsvd1, brlev],
                                         attributes={'positive':
                                                     'down'}), None))

    # Soil level/depth.
    if len(lbcode) != 5 and lbvc == 6:
        if brsvd1 == 0 and brlev == 0:
            # UM populates lblev, brsvd1 and brlev metadata INCORRECTLY,
            # so continue to treat lblev as a soil level.
            coord = DimCoord(model_level_number,
                             long_name='soil_model_level_number',
                             attributes={'positive': 'down'})
            coords_and_dims.append((coord, None))
        elif brsvd1 != brlev:
            # UM populates metadata CORRECTLY,
            # so treat it as the expected (bounded) soil depth.
            coord = DimCoord(blev,
                             standard_name='depth',
                             units='m',
                             bounds=[brsvd1, brlev],
                             attributes={'positive': 'down'})
            coords_and_dims.append((coord, None))

    if \
            (lbvc == 8) and \
            (len(lbcode) != 5 or (len(lbcode) == 5 and 1 not in [lbcode.ix, lbcode.iy])):
        coords_and_dims.append((DimCoord(blev,
                                         long_name='pressure',
                                         units='hPa'), None))

    if \
            (len(lbcode) != 5) and \
            (lbvc == 19):
        coords_and_dims.append(
            (DimCoord(blev,
                      standard_name='air_potential_temperature',
                      units='K',
                      attributes={'positive': 'up'}), None))

    # Hybrid pressure levels (--> scalar coordinates)
    if lbvc == 9:
        model_level_number = DimCoord(model_level_number,
                                      standard_name='model_level_number',
                                      attributes={'positive': 'up'})
        # The following match the hybrid height scheme, but data has the
        # blev and bhlev values the other way around.
        #level_pressure = DimCoord(blev,
        #                          long_name='level_pressure',
        #                          units='Pa',
        #                          bounds=[brlev, brsvd1])
        #sigma = AuxCoord(bhlev,
        #                 long_name='sigma',
        #                 bounds=[bhrlev, brsvd2])
        level_pressure = DimCoord(bhlev,
                                  long_name='level_pressure',
                                  units='Pa',
                                  bounds=[bhrlev, brsvd2])
        sigma = AuxCoord(blev, long_name='sigma', bounds=[brlev, brsvd1])
        coords_and_dims.extend([(model_level_number, None),
                                (level_pressure, None), (sigma, None)])
        factories.append(
            Factory(HybridPressureFactory,
                    [{
                        'long_name': 'level_pressure'
                    }, {
                        'long_name': 'sigma'
                    },
                     Reference('surface_air_pressure')]))

    # Hybrid height levels (--> scalar coordinates + factory)
    if lbvc == 65:
        coords_and_dims.append((DimCoord(model_level_number,
                                         standard_name='model_level_number',
                                         attributes={'positive': 'up'}), None))
        coords_and_dims.append((DimCoord(blev,
                                         long_name='level_height',
                                         units='m',
                                         bounds=[brlev, brsvd1],
                                         attributes={'positive': 'up'}), None))
        coords_and_dims.append((AuxCoord(bhlev,
                                         long_name='sigma',
                                         bounds=[bhrlev, brsvd2]), None))
        factories.append(
            Factory(HybridHeightFactory, [{
                'long_name': 'level_height'
            }, {
                'long_name': 'sigma'
            },
                                          Reference('orography')]))

    return coords_and_dims, factories