def _check_height(self,
                   blev,
                   stash,
                   expect_normal=True,
                   expect_fixed_height=None,
                   dim=None):
     lbvc = 1
     lbcode = _lbcode(0)  # effectively unused in this case
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                           lbvc=lbvc,
                                                           blev=blev,
                                                           lblev=lblev,
                                                           stash=stash,
                                                           bhlev=bhlev,
                                                           bhrlev=bhrlev,
                                                           brsvd1=brsvd1,
                                                           brsvd2=brsvd2,
                                                           brlev=brlev,
                                                           dim=dim)
     if expect_normal:
         expect_result = [(DimCoord(blev,
                                    standard_name='height',
                                    units='m',
                                    attributes={'positive': 'up'}), dim)]
     elif expect_fixed_height:
         expect_result = [(DimCoord(expect_fixed_height,
                                    standard_name='height',
                                    units='m',
                                    attributes={'positive': 'up'}), None)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check(self, lblev=37.0,
            blev=9596.3, brlev=9500.0, brsvd1=9800.0,
            bhlev=0.35, bhrlev=0.31, brsvd2=0.39,
            dim=None):
     lbvc = 65
     lbcode = _lbcode(0)  # unused
     stash = STASH(1, 1, 1)  # unused
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     expect_coords_and_dims = [
         (DimCoord(lblev,
                   standard_name='model_level_number',
                   attributes={'positive': 'up'}), dim)]
     brlev = np.atleast_1d(brlev)
     brsvd1 = np.atleast_1d(brsvd1)
     expect_coords_and_dims.append(
         (DimCoord(blev,
                   long_name='level_height', units='m',
                   bounds=np.vstack((brlev, brsvd1)).T,
                   attributes={'positive': 'up'}), dim))
     bhrlev = np.atleast_1d(bhrlev)
     brsvd2 = np.atleast_1d(brsvd2)
     expect_coords_and_dims.append(
         (AuxCoord(bhlev,
                   long_name='sigma',
                   bounds=np.vstack((bhrlev, brsvd2)).T), dim))
     expect_factories = [(HybridHeightFactory,
                          [{'long_name': 'level_height'},
                           {'long_name': 'sigma'},
                           Reference('orography')])]
     self.assertCoordsAndDimsListsMatch(coords_and_dims,
                                        expect_coords_and_dims)
     self.assertEqual(factories, expect_factories)
 def _check_potm(self, lbcode, blev=130.6, expect_match=True, dim=None):
     lbvc = 19
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                           lbvc=lbvc,
                                                           blev=blev,
                                                           lblev=lblev,
                                                           stash=stash,
                                                           bhlev=bhlev,
                                                           bhrlev=bhrlev,
                                                           brsvd1=brsvd1,
                                                           brsvd2=brsvd2,
                                                           brlev=brlev,
                                                           dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(blev,
                       standard_name='air_potential_temperature',
                       units='K',
                       attributes={'positive': 'up'}), dim)
         ]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_soil_depth(self,
                       lbcode,
                       blev=0.05,
                       brsvd1=0,
                       brlev=0.1,
                       expect_match=True,
                       dim=None):
     lbvc = 6
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd2 = None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                           lbvc=lbvc,
                                                           blev=blev,
                                                           lblev=lblev,
                                                           stash=stash,
                                                           bhlev=bhlev,
                                                           bhrlev=bhrlev,
                                                           brsvd1=brsvd1,
                                                           brsvd2=brsvd2,
                                                           brlev=brlev,
                                                           dim=dim)
     expect_result = []
     if expect_match:
         coord = DimCoord(blev,
                          standard_name='depth',
                          bounds=np.vstack((brsvd1, brlev)).T,
                          units='m',
                          attributes={'positive': 'down'})
         expect_result = [(coord, dim)]
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_soil_level(self,
                       lbcode,
                       lblev=12.3,
                       expect_match=True,
                       dim=None):
     lbvc = 6
     stash = STASH(1, 1, 1)
     brsvd1, brlev = 0, 0
     if hasattr(lblev, '__iter__'):
         brsvd1 = [0] * len(lblev)
         brlev = [0] * len(lblev)
     blev, bhlev, bhrlev, brsvd2 = None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                           lbvc=lbvc,
                                                           blev=blev,
                                                           lblev=lblev,
                                                           stash=stash,
                                                           bhlev=bhlev,
                                                           bhrlev=bhrlev,
                                                           brsvd1=brsvd1,
                                                           brsvd2=brsvd2,
                                                           brlev=brlev,
                                                           dim=dim)
     expect_result = []
     if expect_match:
         coord = DimCoord(lblev,
                          long_name='soil_model_level_number',
                          attributes={'positive': 'down'})
         expect_result = [(coord, dim)]
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check(self, lblev=37.0,
            blev=9596.3, brlev=9500.0, brsvd1=9800.0,
            bhlev=0.35, bhrlev=0.31, brsvd2=0.39,
            dim=None):
     lbvc = 65
     lbcode = _lbcode(0)  # unused
     stash = STASH(1, 1, 1)  # unused
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     expect_coords_and_dims = [
         (DimCoord(lblev,
                   standard_name='model_level_number',
                   attributes={'positive': 'up'}), dim)]
     brlev = np.atleast_1d(brlev)
     brsvd1 = np.atleast_1d(brsvd1)
     expect_coords_and_dims.append(
         (DimCoord(blev,
                   long_name='level_height', units='m',
                   bounds=np.vstack((brlev, brsvd1)).T,
                   attributes={'positive': 'up'}), dim))
     bhrlev = np.atleast_1d(bhrlev)
     brsvd2 = np.atleast_1d(brsvd2)
     expect_coords_and_dims.append(
         (AuxCoord(bhlev,
                   long_name='sigma',
                   bounds=np.vstack((bhrlev, brsvd2)).T), dim))
     expect_factories = [(HybridHeightFactory,
                          [{'long_name': 'level_height'},
                           {'long_name': 'sigma'},
                           Reference('orography')])]
     self.assertCoordsAndDimsListsMatch(coords_and_dims,
                                        expect_coords_and_dims)
     self.assertEqual(factories, expect_factories)
 def _check_depth(self,
                  lbcode,
                  lblev=23.0,
                  blev=123.4,
                  brlev=0.0,
                  brsvd1=0.0,
                  expect_bounds=True,
                  expect_match=True,
                  expect_mixed=False,
                  dim=None):
     lbvc = 2
     stash = STASH(1, 1, 1)
     bhlev, bhrlev, brsvd2 = None, None, None
     coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                           lbvc=lbvc,
                                                           blev=blev,
                                                           lblev=lblev,
                                                           stash=stash,
                                                           bhlev=bhlev,
                                                           bhrlev=bhrlev,
                                                           brsvd1=brsvd1,
                                                           brsvd2=brsvd2,
                                                           brlev=brlev,
                                                           dim=dim)
     if expect_match:
         expect_result = [(DimCoord(lblev,
                                    standard_name='model_level_number',
                                    attributes={'positive': 'down'}), dim)]
         if expect_bounds:
             brsvd1 = np.atleast_1d(brsvd1)
             brlev = np.atleast_1d(brlev)
             if expect_mixed:
                 lower = np.where(brsvd1 == brlev, blev, brsvd1)
                 upper = np.where(brsvd1 == brlev, blev, brlev)
             else:
                 lower, upper = brsvd1, brlev
             bounds = np.vstack((lower, upper)).T
             expect_result.append((DimCoord(blev,
                                            standard_name='depth',
                                            units='m',
                                            bounds=bounds,
                                            attributes={'positive':
                                                        'down'}), dim))
         else:
             expect_result.append((DimCoord(blev,
                                            standard_name='depth',
                                            units='m',
                                            attributes={'positive':
                                                        'down'}), dim))
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def test_unknown_lbvc(self):
     lbvc = 999
     blev, lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None, None
     lbcode = _lbcode(0)  # unused
     stash = STASH(1, 1, 1)  # unused
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev)
     self.assertEqual(coords_and_dims, [])
     self.assertEqual(factories, [])
 def test_unknown_lbvc(self):
     lbvc = 999
     blev, lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None, None
     lbcode = _lbcode(0)  # unused
     stash = STASH(1, 1, 1)  # unused
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev)
     self.assertEqual(coords_and_dims, [])
     self.assertEqual(factories, [])
    def _check(self,
               lblev=37.0,
               bhlev=850.1,
               bhrlev=810.0,
               brsvd2=875.0,
               blev=0.15,
               brlev=0.11,
               brsvd1=0.19,
               expect_match=True,
               dim=None):
        lbvc = 9
        lbcode = _lbcode(0)  # unused
        stash = STASH(1, 1, 1)  # unused
        coords_and_dims, factories = _convert_vertical_coords(lbcode=lbcode,
                                                              lbvc=lbvc,
                                                              blev=blev,
                                                              lblev=lblev,
                                                              stash=stash,
                                                              bhlev=bhlev,
                                                              bhrlev=bhrlev,
                                                              brsvd1=brsvd1,
                                                              brsvd2=brsvd2,
                                                              brlev=brlev,
                                                              dim=dim)
        expect_coords_and_dims = [(DimCoord(lblev,
                                            standard_name='model_level_number',
                                            attributes={'positive':
                                                        'up'}), dim)]

        bhrlev = np.atleast_1d(bhrlev)
        brsvd2 = np.atleast_1d(brsvd2)
        expect_coords_and_dims.append((DimCoord(bhlev,
                                                long_name='level_pressure',
                                                units='Pa',
                                                bounds=np.vstack(
                                                    (bhrlev, brsvd2)).T), dim))
        brlev = np.atleast_1d(brlev)
        brsvd1 = np.atleast_1d(brsvd1)
        expect_coords_and_dims.append((AuxCoord(blev,
                                                long_name='sigma',
                                                bounds=np.vstack(
                                                    (brlev, brsvd1)).T), dim))
        expect_factories = [(HybridPressureFactory,
                             [{
                                 'long_name': 'level_pressure'
                             }, {
                                 'long_name': 'sigma'
                             },
                              Reference('surface_air_pressure')])]
        self.assertCoordsAndDimsListsMatch(coords_and_dims,
                                           expect_coords_and_dims)
        self.assertEqual(factories, expect_factories)
 def _check_pressure(self, lbcode, blev=250.3, expect_match=True, dim=None):
     lbvc = 8
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(blev, long_name='pressure', units='hPa'), dim)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_pressure(self, lbcode, blev=250.3, expect_match=True, dim=None):
     lbvc = 8
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(blev, long_name='pressure', units='hPa'), dim)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_potm(self, lbcode, blev=130.6, expect_match=True, dim=None):
     lbvc = 19
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(blev, standard_name='air_potential_temperature',
                       units='K', attributes={'positive': 'up'}), dim)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_soil_depth(self, lbcode, blev=0.05, brsvd1=0, brlev=0.1,
                       expect_match=True, dim=None):
     lbvc = 6
     stash = STASH(1, 1, 1)
     lblev, bhlev, bhrlev, brsvd2 = None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     expect_result = []
     if expect_match:
         coord = DimCoord(blev, standard_name='depth',
                          bounds=np.vstack((brsvd1, brlev)).T,
                          units='m', attributes={'positive': 'down'})
         expect_result = [(coord, dim)]
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_soil_level(self, lbcode, lblev=12.3, expect_match=True,
                       dim=None):
     lbvc = 6
     stash = STASH(1, 1, 1)
     blev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(lblev, long_name='soil_model_level_number',
                       attributes={'positive': 'down'}), dim)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_depth(self, lbcode, lblev=23.0, blev=123.4, brlev=0.0,
                  brsvd1=0.0, expect_bounds=True, expect_match=True,
                  expect_mixed=False, dim=None):
     lbvc = 2
     stash = STASH(1, 1, 1)
     bhlev, bhrlev, brsvd2 = None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_match:
         expect_result = [
             (DimCoord(lblev,
                       standard_name='model_level_number',
                       attributes={'positive': 'down'}), dim)]
         if expect_bounds:
             brsvd1 = np.atleast_1d(brsvd1)
             brlev = np.atleast_1d(brlev)
             if expect_mixed:
                 lower = np.where(brsvd1 == brlev, blev, brsvd1)
                 upper = np.where(brsvd1 == brlev, blev, brlev)
             else:
                 lower, upper = brsvd1, brlev
             bounds = np.vstack((lower, upper)).T
             expect_result.append(
                 (DimCoord(blev, standard_name='depth',
                           units='m',
                           bounds=bounds,
                           attributes={'positive': 'down'}), dim))
         else:
             expect_result.append(
                 (DimCoord(blev, standard_name='depth', units='m',
                           attributes={'positive': 'down'}), dim))
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
 def _check_height(self, blev, stash,
                   expect_normal=True, expect_fixed_height=None, dim=None):
     lbvc = 1
     lbcode = _lbcode(0)  # effectively unused in this case
     lblev, bhlev, bhrlev, brsvd1, brsvd2, brlev = \
         None, None, None, None, None, None
     coords_and_dims, factories = _convert_vertical_coords(
         lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
         bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
         brlev=brlev, dim=dim)
     if expect_normal:
         expect_result = [
             (DimCoord(blev, standard_name='height', units='m',
                       attributes={'positive': 'up'}),
              dim)]
     elif expect_fixed_height:
         expect_result = [
             (DimCoord(expect_fixed_height, standard_name='height',
                       units='m', attributes={'positive': 'up'}),
              None)]
     else:
         expect_result = []
     self.assertCoordsAndDimsListsMatch(coords_and_dims, expect_result)
     self.assertEqual(factories, [])
    def _check(self, lblev=37.0,
               bhlev=850.1, bhrlev=810.0, brsvd2=875.0,
               blev=0.15, brlev=0.11, brsvd1=0.19,
               expect_match=True, dim=None):
        lbvc = 9
        lbcode = _lbcode(0)  # unused
        stash = STASH(1, 1, 1)  # unused
        coords_and_dims, factories = _convert_vertical_coords(
            lbcode=lbcode, lbvc=lbvc, blev=blev, lblev=lblev, stash=stash,
            bhlev=bhlev, bhrlev=bhrlev, brsvd1=brsvd1, brsvd2=brsvd2,
            brlev=brlev, dim=dim)
        expect_coords_and_dims = [
            (DimCoord(lblev,
                      standard_name='model_level_number',
                      attributes={'positive': 'up'}), dim)]

        bhrlev = np.atleast_1d(bhrlev)
        brsvd2 = np.atleast_1d(brsvd2)
        expect_coords_and_dims.append(
            (DimCoord(bhlev,
                      long_name='level_pressure',
                      units='Pa',
                      bounds=np.vstack((bhrlev, brsvd2)).T), dim))
        brlev = np.atleast_1d(brlev)
        brsvd1 = np.atleast_1d(brsvd1)
        expect_coords_and_dims.append(
            (AuxCoord(blev,
                      long_name='sigma',
                      bounds=np.vstack((brlev, brsvd1)).T), dim))
        expect_factories = [(HybridPressureFactory,
                             [{'long_name': 'level_pressure'},
                              {'long_name': 'sigma'},
                              Reference('surface_air_pressure')])]
        self.assertCoordsAndDimsListsMatch(coords_and_dims,
                                           expect_coords_and_dims)
        self.assertEqual(factories, expect_factories)
Example #19
0
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)
Example #20
0
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)
Example #21
0
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 _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)