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_invalid_units(self): # Mock converter() function that returns an invalid # units string amongst the collection of other elements. factories = None references = None standard_name = None long_name = None units = 'wibble' # Invalid unit. attributes = dict(source='test') cell_methods = None dim_coords_and_dims = None aux_coords_and_dims = None metadata = ConversionMetadata(factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims) converter = mock.Mock(return_value=metadata) data = np.arange(3.) field = mock.Mock(core_data=lambda: data, bmdi=9999., realised_dtype=data.dtype) with warnings.catch_warnings(record=True) as warn: warnings.simplefilter("always") cube, factories, references = _make_cube(field, converter) # Check attributes dictionary is correctly populated. expected_attributes = attributes.copy() expected_attributes['invalid_units'] = units self.assertEqual(cube.attributes, expected_attributes) # Check warning was raised. self.assertEqual(len(warn), 1) exp_emsg = 'invalid units {!r}'.format(units) self.assertRegex(str(warn[0]), exp_emsg)
def convert(f): """ Converts a PP field into the corresponding items of Cube metadata. Args: * f: A :class:`iris.fileformats.pp.PPField` object. Returns: A :class:`iris.fileformats.rules.ConversionMetadata` object. """ factories = [] aux_coords_and_dims = [] # "Normal" (non-cross-sectional) Time values (--> scalar coordinates) time_coords_and_dims = _convert_time_coords( lbcode=f.lbcode, lbtim=f.lbtim, epoch_hours_unit=f.time_unit('hours'), t1=f.t1, t2=f.t2, lbft=f.lbft) aux_coords_and_dims.extend(time_coords_and_dims) # "Normal" (non-cross-sectional) Vertical levels # (--> scalar coordinates and factories) vertical_coords_and_dims, vertical_factories = \ _convert_vertical_coords( lbcode=f.lbcode, lbvc=f.lbvc, blev=f.blev, lblev=f.lblev, stash=f.stash, bhlev=f.bhlev, bhrlev=f.bhrlev, brsvd1=f.brsvd[0], brsvd2=f.brsvd[1], brlev=f.brlev) aux_coords_and_dims.extend(vertical_coords_and_dims) factories.extend(vertical_factories) # Realization (aka ensemble) (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_realization_coords(lbrsvd4=f.lbrsvd[3])) # Pseudo-level coordinate (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_pseudo_level_coords(lbuser5=f.lbuser[4])) # All the other rules. references, standard_name, long_name, units, attributes, cell_methods, \ dim_coords_and_dims, other_aux_coords_and_dims = _all_other_rules(f) aux_coords_and_dims.extend(other_aux_coords_and_dims) return ConversionMetadata(factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims)
def _convert_collation(collation): """ Converts a FieldCollation into the corresponding items of Cube metadata. Args: * collation: A FieldCollation object. Returns: A :class:`iris.fileformats.rules.ConversionMetadata` object. .. note: This is the 'loader.converter', in the control structure passed to the generic rules code, :meth:`iris.fileformats.rules.load_cubes`. """ from iris.fileformats.rules import ConversionMetadata from iris.fileformats.pp_rules import (_convert_time_coords, _convert_vertical_coords, _convert_scalar_realization_coords, _convert_scalar_pseudo_level_coords, _all_other_rules) # For all the scalar conversions, all fields in the collation will # give the same result, so the choice is arbitrary. field = collation.fields[0] # Call "all other" rules. (references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims) = _all_other_rules(field) # Adjust any dimension bindings to account for the extra leading # dimensions added by the collation. if collation.vector_dims_shape: def _adjust_dims(coords_and_dims, n_dims): def adjust(dims): if dims is not None: dims += n_dims return dims return [(coord, adjust(dims)) for coord, dims in coords_and_dims] n_collation_dims = len(collation.vector_dims_shape) dim_coords_and_dims = _adjust_dims(dim_coords_and_dims, n_collation_dims) aux_coords_and_dims = _adjust_dims(aux_coords_and_dims, n_collation_dims) # Dimensions to which we've already assigned dimension coordinates. dim_coord_dims = set() # Helper call to choose which coords are dimensions and which auxiliary. def _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, aux_coords_and_dims): def key_func(item): return _HINTS.get(item[0].name(), len(_HINTS)) # Target the first DimCoord for a dimension at dim_coords, # and target everything else at aux_coords. for coord, dims in sorted(coords_and_dims, key=key_func): if (isinstance(coord, DimCoord) and dims is not None and len(dims) == 1 and dims[0] not in dim_coord_dims): dim_coords_and_dims.append((coord, dims)) dim_coord_dims.add(dims[0]) else: aux_coords_and_dims.append((coord, dims)) # Call "time" rules. # # For "normal" (non-cross-sectional) time values. vector_headers = collation.element_arrays_and_dims # If the collation doesn't define a vector of values for a # particular header then it must be constant over all fields in the # collation. In which case it's safe to get the value from any field. t1, t1_dims = vector_headers.get('t1', (field.t1, ())) t2, t2_dims = vector_headers.get('t2', (field.t2, ())) lbft, lbft_dims = vector_headers.get('lbft', (field.lbft, ())) coords_and_dims = _convert_time_coords(field.lbcode, field.lbtim, field.time_unit('hours'), t1, t2, lbft, t1_dims, t2_dims, lbft_dims) # Bind resulting coordinates to dimensions, where suitable. _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, aux_coords_and_dims) # Call "vertical" rules. # # "Normal" (non-cross-sectional) vertical levels blev, blev_dims = vector_headers.get('blev', (field.blev, ())) lblev, lblev_dims = vector_headers.get('lblev', (field.lblev, ())) bhlev, bhlev_dims = vector_headers.get('bhlev', (field.bhlev, ())) bhrlev, bhrlev_dims = vector_headers.get('bhrlev', (field.bhrlev, ())) brsvd1, brsvd1_dims = vector_headers.get('brsvd1', (field.brsvd[0], ())) brsvd2, brsvd2_dims = vector_headers.get('brsvd2', (field.brsvd[1], ())) brlev, brlev_dims = vector_headers.get('brlev', (field.brlev, ())) # Find all the non-trivial dimension values dims = set( filter(None, [ blev_dims, lblev_dims, bhlev_dims, bhrlev_dims, brsvd1_dims, brsvd2_dims, brlev_dims ])) if len(dims) > 1: raise TranslationError('Unsupported multiple values for vertical ' 'dimension.') if dims: v_dims = dims.pop() if len(v_dims) > 1: raise TranslationError('Unsupported multi-dimension vertical ' 'headers.') else: v_dims = () coords_and_dims, factories = _convert_vertical_coords( field.lbcode, field.lbvc, blev, lblev, field.stash, bhlev, bhrlev, brsvd1, brsvd2, brlev, v_dims) # Bind resulting coordinates to dimensions, where suitable. _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, aux_coords_and_dims) # Realization (aka ensemble) (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_realization_coords(lbrsvd4=field.lbrsvd[3])) # Pseudo-level coordinate (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_pseudo_level_coords(lbuser5=field.lbuser[4])) return ConversionMetadata(factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims)
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)
def converter(field): return ConversionMetadata([factory], [], "", "", "", {}, [], [], [])
def _convert_collation(collation): """ Converts a FieldCollation into the corresponding items of Cube metadata. Args: * collation: A FieldCollation object. Returns: A :class:`iris.fileformats.rules.ConversionMetadata` object. """ # For all the scalar conversions all fields in the collation will # give the same result, so the choice is arbitrary. field = collation.fields[0] # All the "other" rules. (references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims) = _all_other_rules(field) # Adjust any dimension bindings to account for the extra leading # dimensions added by the collation. if collation.vector_dims_shape: n_collation_dims = len(collation.vector_dims_shape) dim_coords_and_dims = _adjust_dims(dim_coords_and_dims, n_collation_dims) aux_coords_and_dims = _adjust_dims(aux_coords_and_dims, n_collation_dims) # "Normal" (non-cross-sectional) time values vector_headers = collation.element_arrays_and_dims # If the collation doesn't define a vector of values for a # particular header then it must be constant over all fields in the # collation. In which case it's safe to get the value from any field. t1, t1_dims = vector_headers.get('t1', (field.t1, ())) t2, t2_dims = vector_headers.get('t2', (field.t2, ())) lbft, lbft_dims = vector_headers.get('lbft', (field.lbft, ())) coords_and_dims = _convert_time_coords(field.lbcode, field.lbtim, field.time_unit('hours'), t1, t2, lbft, t1_dims, t2_dims, lbft_dims) dim_coord_dims = set() _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, aux_coords_and_dims) # "Normal" (non-cross-sectional) vertical levels blev, blev_dims = vector_headers.get('blev', (field.blev, ())) lblev, lblev_dims = vector_headers.get('lblev', (field.lblev, ())) bhlev, bhlev_dims = vector_headers.get('bhlev', (field.bhlev, ())) bhrlev, bhrlev_dims = vector_headers.get('bhrlev', (field.bhrlev, ())) brsvd1, brsvd1_dims = vector_headers.get('brsvd1', (field.brsvd[0], ())) brsvd2, brsvd2_dims = vector_headers.get('brsvd2', (field.brsvd[1], ())) brlev, brlev_dims = vector_headers.get('brlev', (field.brlev, ())) # Find all the non-trivial dimension values dims = set( filter(None, [ blev_dims, lblev_dims, bhlev_dims, bhrlev_dims, brsvd1_dims, brsvd2_dims, brlev_dims ])) if len(dims) > 1: raise TranslationError('Unsupported multiple values for vertical ' 'dimension.') if dims: v_dims = dims.pop() if len(v_dims) > 1: raise TranslationError('Unsupported multi-dimension vertical ' 'headers.') else: v_dims = () coords_and_dims, factories = _convert_vertical_coords( field.lbcode, field.lbvc, blev, lblev, field.stash, bhlev, bhrlev, brsvd1, brsvd2, brlev, v_dims) _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, aux_coords_and_dims) # Realization (aka ensemble) (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_realization_coords(lbrsvd4=field.lbrsvd[3])) # Pseudo-level coordinate (--> scalar coordinates) aux_coords_and_dims.extend( _convert_scalar_pseudo_level_coords(lbuser5=field.lbuser[4])) return ConversionMetadata(factories, references, standard_name, long_name, units, attributes, cell_methods, dim_coords_and_dims, aux_coords_and_dims)
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)