def check_latitude(self, ds):
        '''
        Check variable(s) that define latitude and are defined correctly according to CF.

        CF §4.1 Variables representing latitude must always explicitly include
        the units attribute; there is no default value.  The recommended unit
        of latitude is degrees_north. Also acceptable are degree_north,
        degree_N, degrees_N, degreeN, and degreesN.

        Optionally, the latitude type may be indicated additionally by
        providing the standard_name attribute with the value latitude, and/or
        the axis attribute with the value Y.

        - Four checks per latitude variable
        - (H) latitude has units attribute
        - (M) latitude has an allowed units attribute
        - (L) latitude uses degrees_north (if not in rotated pole)
        - (M) latitude defines either standard_name or axis

        :param netCDF4.Dataset ds: An open netCDF dataset
        :rtype: list
        :return: List of results
        '''
        ret_val = []

        allowed_lat_units = [
            'degrees_north',
            'degree_north',
            'degree_n',
            'degrees_n',
            'degreen',
            'degreesn'
        ]

        # Determine the grid mappings in this dataset
        grid_mapping = []
        grid_mapping_variables = cfutil.get_grid_mapping_variables(ds)
        for name in grid_mapping_variables:
            variable = ds.variables[name]
            grid_mapping_name = getattr(variable, 'grid_mapping_name', None)
            if grid_mapping_name:
                grid_mapping.append(grid_mapping_name)

        latitude_variables = cfutil.get_latitude_variables(ds)
        for latitude in latitude_variables:
            variable = ds.variables[latitude]
            units = getattr(variable, 'units', None)
            units_is_string = isinstance(units, basestring)
            standard_name = getattr(variable, 'standard_name', None)
            axis = getattr(variable, 'axis', None)

            # Check that latitude defines units
            valid_latitude = TestCtx(BaseCheck.HIGH, self.section_titles['4.1'])
            valid_latitude.assert_true(units is not None,
                                       "latitude variable '{}' must define units".format(latitude))
            ret_val.append(valid_latitude.to_result())

            # Check that latitude uses allowed units
            allowed_units = TestCtx(BaseCheck.MEDIUM, self.section_titles['4.1'])
            if standard_name == 'grid_latitude':
                e_n_units = cfutil.VALID_LAT_UNITS | cfutil.VALID_LON_UNITS
                # check that the units aren't in east and north degrees units,
                # but are convertible to angular units
                allowed_units.assert_true(units not in e_n_units and
                                          Unit(units) == Unit('degree'),
                                          "Grid latitude variable '{}' should use degree equivalent units without east or north components. "
                                          "Current units are {}".format(latitude, units))
            else:
                allowed_units.assert_true(units_is_string and units.lower() in allowed_lat_units,
                                          "latitude variable '{}' should define valid units for latitude"
                                          "".format(latitude))
            ret_val.append(allowed_units.to_result())

            # Check that latitude uses degrees_north
            if standard_name == 'latitude' and units != 'degrees_north':
                # This is only a recommendation and we won't penalize but we
                # will include a recommended action.
                msg = ("CF recommends latitude variable '{}' to use units degrees_north"
                       "".format(latitude))
                recommended_units = Result(BaseCheck.LOW, (1, 1), self.section_titles['4.1'], [msg])
                ret_val.append(recommended_units)

            y_variables = ds.get_variables_by_attributes(axis='Y')
            # Check that latitude defines either standard_name or axis
            definition = TestCtx(BaseCheck.MEDIUM, self.section_titles['4.1'])
            definition.assert_true(standard_name == 'latitude' or axis == 'Y' or y_variables != [],
                                   "latitude variable '{}' should define standard_name='latitude' or axis='Y'"
                                   "".format(latitude))
            ret_val.append(definition.to_result())

        return ret_val
Check variable(s) that define latitude and are defined correctly according to CF.

        CF §4.1 Variables representing latitude must always explicitly include
        the units attribute; there is no default value.  The recommended unit
        of latitude is degrees_north. Also acceptable are degree_north,
        degree_N, degrees_N, degreeN, and degreesN.

        Optionally, the latitude type may be indicated additionally by
        providing the standard_name attribute with the value latitude, and/or
        the axis attribute with the value Y.

        - Four checks per latitude variable
        - (H) latitude has units attribute
        - (M) latitude has an allowed units attribute
        - (L) latitude uses degrees_north (if not in rotated pole)
        - (M) latitude defines either standard_name or axis

        :param netCDF4.Dataset ds: An open netCDF dataset
        :rtype: list
        :return: List of results