Пример #1
0
    def check_timeseries_id(self, dataset):
        '''
        Checks that if a variable exists for the time series id it has the appropriate attributes

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'Required variable for time series identifier')
        recommended_ctx = TestCtx(BaseCheck.MEDIUM, 'Recommended attributes for the timeSeries variable')
        # A variable with cf_role="timeseries_id" MUST exist for this to be a valid timeseries incomplete
        timeseries_ids = dataset.get_variables_by_attributes(cf_role='timeseries_id')
        required_ctx.assert_true(timeseries_ids, 'a unique variable must define attribute cf_role="timeseries_id"')
        results.append(required_ctx.to_result())
        if not timeseries_ids:
            return results

        timevar = util.get_time_variable(dataset)
        nc_timevar = dataset.variables[timevar]
        time_dimensions = nc_timevar.dimensions

        timeseries_variable = timeseries_ids[0]
        dims = timeseries_variable.dimensions
        required_ctx.assert_true(
            time_dimensions and time_dimensions[0] == dims[0],
            '{} must have a dimension and that dimension must be shared by the time variable'.format(timeseries_variable.name)
        )
        recommended_ctx.assert_true(
            getattr(timeseries_variable, 'long_name', '') != "",
            "long_name attribute should exist and not be empty"
        )
        results.append(recommended_ctx.to_result())
        return results
Пример #2
0
    def check_bounds_variables(self, dataset):
        '''
        Checks the grid boundary variables.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        recommended_ctx = TestCtx(BaseCheck.MEDIUM, 'Recommended variables to describe grid boundaries')

        bounds_map = {
            'lat_bounds': {
                'units': 'degrees_north',
                'comment': 'latitude values at the north and south bounds of each pixel.'
            },
            'lon_bounds': {
                'units': 'degrees_east',
                'comment': 'longitude values at the west and east bounds of each pixel.'
            },
            'z_bounds': {
                'comment': 'z bounds for each z value',
            },
            'time_bounds': {
                'comment': 'time bounds for each time value'
            }
        }

        bounds_variables = [v.bounds for v in dataset.get_variables_by_attributes(bounds=lambda x: x is not None)]

        for variable in bounds_variables:
            ncvar = dataset.variables.get(variable, {})
            recommended_ctx.assert_true(ncvar != {}, 'a variable {} should exist as indicated by a bounds attribute'.format(variable))
            if ncvar == {}:
                continue

            units = getattr(ncvar, 'units', '')
            if variable in bounds_map and 'units' in bounds_map[variable]:
                recommended_ctx.assert_true(
                    units == bounds_map[variable]['units'],
                    'variable {} should have units {}'.format(variable, bounds_map[variable]['units'])
                )
            else:
                recommended_ctx.assert_true(
                    units != '',
                    'variable {} should have a units attribute that is not empty'.format(variable)
                )

            comment = getattr(ncvar, 'comment', '')
            recommended_ctx.assert_true(
                comment != '',
                'variable {} should have a comment and not be empty'
            )

        return recommended_ctx.to_result()
Пример #3
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consitent with a time series orthogonal dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are time-series orthogonal feature types')
        message = '{} must be a valid timeseries feature type. It must have dimensions of (timeSeries, time) or (time).'
        message += ' And x, y and z coordinates must have dimensions (timeSeries) or be dimensionless'
        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_timeseries(dataset, variable) or util.is_multi_timeseries_orthogonal(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        return required_ctx.to_result()
Пример #4
0
    def check_timeseries_id(self, dataset):
        '''
        Checks that if a variable exists for the time series id it has the appropriate attributes

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        timeseries_ids = dataset.get_variables_by_attributes(cf_role='timeseries_id')
        # No need to check
        if not timeseries_ids:
            return
        test_ctx = TestCtx(BaseCheck.MEDIUM, 'Recommended attributes for the timeSeries variable')
        timeseries_variable = timeseries_ids[0]
        test_ctx.assert_true(
            getattr(timeseries_variable, 'long_name', '') != "",
            "long_name attribute should exist and not be empty"
        )
        return test_ctx.to_result()
Пример #5
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a profile-orthogonal dataset.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are profile-orthogonal feature types')

        message = '{} must be a valid profile-orthogonal feature type. It must have dimensions of (profile, depth).'
        message += ' x and y should have dimensions of (profile), z should have dimension of (depth) and t should have dimension (profile)'
        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_profile_orthogonal(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consitent with a trajectory profile incomplete dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(
            BaseCheck.HIGH,
            'All geophysical variables are trajectory profile incomplete feature types'
        )

        message = '{} must be a valid trajectory profile incomplete feature type. It and z must have dimensions of (trajectory, obs, nzMax).'
        message += ' Also, x, y, and t must have dimensions (trajectory, obs).'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_trajectory_profile_incomplete(dataset, variable)
            required_ctx.assert_true(is_valid, message.format(variable))
        results.append(required_ctx.to_result())
        return results
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consitent with a trajectory profile orthogonal dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are trajectory profile orthogonal feature types')

        message = '{} must be a valid trajectory profile orthogonal feature type. It must have dimensions of (trajectory, obs, z).'
        message += ' Also, x, y, and t must have dimensions (trajectory, obs). z must be a coordinate variable with dimensions (z).'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_trajectory_profile_orthogonal(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
Пример #8
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consitent with a trajectory dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are trajectory feature types')

        message = ("{} must be a valid trajectory feature type. It must have dimensions of (trajectoryID, time)."
                   " And all coordinates must have dimensions (trajectoryID, time)")
        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_cf_trajectory(dataset, variable)
            is_valid = is_valid or util.is_single_trajectory(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a timeseries-profile-incomplete dataset.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are timeseries-profile-incomplete feature types')

        message = '{} must be a valid timeseries-profile-incomplete feature type.'
        message += ' it must have dimensions (station, nTimeMax, zMax). x and y must have dimensions (station).'
        message += ' time must have dimensions (station, nTimeMax). And z must have dimensions (station, nTimeMax, zMax).'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_timeseries_profile_incomplete(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
Пример #10
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a regular gridded dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(
            BaseCheck.HIGH,
            'All geophysical variables are regular gridded feature types')

        message = '{} must be a valid regular gridded feature type. It must have dimensions (t, z, y, x)'
        message += ' and each dimension must be a coordinate variable with a dimension with the same name'
        message += ' as the variable. z is optional.'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_2d_regular_grid(dataset, variable)
            is_valid = is_valid or util.is_3d_regular_grid(dataset, variable)
            required_ctx.assert_true(is_valid, message.format(variable))
        results.append(required_ctx.to_result())
        return results
Пример #11
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a timeseries-profile-incomplete dataset.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(
            BaseCheck.HIGH,
            'All geophysical variables are timeseries-profile-incomplete feature types'
        )

        message = '{} must be a valid timeseries-profile-incomplete feature type.'
        message += ' it must have dimensions (station, nTimeMax, zMax). x and y must have dimensions (station).'
        message += ' time must have dimensions (station, nTimeMax). And z must have dimensions (station, nTimeMax, zMax).'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_timeseries_profile_incomplete(dataset, variable)
            required_ctx.assert_true(is_valid, message.format(variable))
        results.append(required_ctx.to_result())
        return results
Пример #12
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a regular gridded dataset

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are regular gridded feature types')

        message = '{} must be a valid regular gridded feature type. It must have dimensions (t, z, y, x)'
        message += ' and each dimension must be a coordinate variable with a dimension with the same name'
        message += ' as the variable. z is optional.'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_2d_regular_grid(dataset, variable)
            is_valid = is_valid or util.is_3d_regular_grid(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
Пример #13
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consistent with a timeseries-profile-orthogonal dataset.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'All geophysical variables are timeseries-profile-orthogonal feature types')

        message = '{} must be a valid profile-orthogonal feature type. It must have dimensions of (station, time, z).'
        message += ' If it\'s a single station, it must have dimensions (time, z). x and y dimensions must be scalar or have'
        message += ' dimensions (station). time must be a coordinate variable with dimension (time) and z must be a'
        message += ' coordinate variabel with dimension (z).'

        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_timeseries_profile_single_station(dataset, variable)
            is_valid = is_valid or util.is_timeseries_profile_multi_station(dataset, variable)
            required_ctx.assert_true(
                is_valid,
                message.format(variable)
            )
        results.append(required_ctx.to_result())
        return results
Пример #14
0
 def check_required_attributes(self, dataset):
     '''
     Verifies that the dataset contains the NCEI required and highly recommended global attributes
     '''
     results = []
     required_ctx = TestCtx(BaseCheck.HIGH,
                            'Required Global Attributes for Timeseries')
     required_ctx.assert_true(
         getattr(dataset, 'nodc_template_version',
                 '').lower() == self.valid_templates[0].lower(),
         'nodc_template_version attribute must be {}'.format(
             self.valid_templates[0]))
     required_ctx.assert_true(
         getattr(dataset, 'cdm_data_type', '') == 'Point',
         'cdm_data_type attribute must be set to Point')
     required_ctx.assert_true(
         getattr(dataset, 'featureType', '') == 'point',
         'featureType attribute must be set to point')
     results.append(required_ctx.to_result())
     return results
Пример #15
0
    def check_trajectory_id(self, dataset):
        '''
        Checks that if a variable exists for the trajectory id it has the appropriate attributes

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        exists_ctx = TestCtx(BaseCheck.MEDIUM, 'Variable defining "trajectory_id" exists')
        trajectory_ids = dataset.get_variables_by_attributes(cf_role='trajectory_id')
        # No need to check
        exists_ctx.assert_true(trajectory_ids, 'variable defining cf_role="trajectory_id" exists')
        if not trajectory_ids:
            return exists_ctx.to_result()
        results.append(exists_ctx.to_result())
        test_ctx = TestCtx(BaseCheck.MEDIUM, 'Recommended attributes for the {} variable'.format(trajectory_ids[0].name))
        test_ctx.assert_true(
            getattr(trajectory_ids[0], 'long_name', '') != "",
            "long_name attribute should exist and not be empty"
        )
        results.append(test_ctx.to_result())
        return results
Пример #16
0
 def check_required_attributes(self, dataset):
     """
     Verifies that the dataset contains the NCEI required and highly recommended global attributes
     """
     results = []
     required_ctx = TestCtx(BaseCheck.HIGH, "Required Global Attributes for Timeseries")
     required_ctx.assert_true(
         getattr(dataset, "nodc_template_version", "").lower() == self.valid_templates[0].lower(),
         "nodc_template_version attribute must be {}".format(self.valid_templates[0]),
     )
     required_ctx.assert_true(
         getattr(dataset, "cdm_data_type", "") == "Point", "cdm_data_type attribute must be set to Point"
     )
     required_ctx.assert_true(
         getattr(dataset, "featureType", "") == "point", "featureType attribute must be set to point"
     )
     results.append(required_ctx.to_result())
     return results
Пример #17
0
    def check_required_attributes(self, dataset):
        '''
        Feature type specific check of global required and highly recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH,
                               'Required Global Attributes for Grid')
        required_ctx.assert_true(
            getattr(dataset, 'ncei_template_version',
                    '').lower() == self.valid_templates[0].lower(),
            'ncei_template_version attribute must be {}'.format(
                self.valid_templates[0]))
        required_ctx.assert_true(
            getattr(dataset, 'cdm_data_type', '') == 'Grid',
            'cdm_data_type attribute must be set to Grid')
        required_ctx.assert_true(
            getattr(dataset, 'featureType', '') == 'grid',
            'featureType attribute must be set to grid')
        results.append(required_ctx.to_result())
        return results
Пример #18
0
    def check_required_attributes(self, dataset):
        '''
        Feature type specific check of global required and highly recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(
            BaseCheck.HIGH,
            'Required Global Attributes for Timeseries Profile Incomplete Time and Depth'
        )
        required_ctx.assert_true(
            getattr(dataset, 'ncei_template_version',
                    '') == self.valid_templates[0],
            'ncei_template_version attribute must be {}'.format(
                self.valid_templates[0]))
        required_ctx.assert_true(
            getattr(dataset, 'cdm_data_type', '') == 'Station',
            'cdm_data_type attribute must be set to Station')
        required_ctx.assert_true(
            getattr(dataset, 'featureType', '') == 'timeSeriesProfile',
            'featureType attribute must be set to timeSeriesProfile')
        results.append(required_ctx.to_result())
        return results
Пример #19
0
    def check_required_attributes(self, dataset):
        '''
        Feature type specific check of global required and highly recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'Required Global Attributes for Timeseries Profile Incomplete Time and Depth')
        required_ctx.assert_true(
            getattr(dataset, 'ncei_template_version', '') == self.valid_templates[0],
            'ncei_template_version attribute must be {}'.format(self.valid_templates[0])
        )
        required_ctx.assert_true(
            getattr(dataset, 'cdm_data_type', '') == 'Station',
            'cdm_data_type attribute must be set to Station'
        )
        required_ctx.assert_true(
            getattr(dataset, 'featureType', '') == 'timeSeriesProfile',
            'featureType attribute must be set to timeSeriesProfile'
        )
        results.append(required_ctx.to_result())
        return results
Пример #20
0
    def check_required_attributes(self, dataset):
        '''
        Feature type specific check of global required and highly recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH, 'Required Global Attributes for Trajectory dataset')
        required_ctx.assert_true(
            getattr(dataset, 'nodc_template_version', '').lower() == self.valid_templates[0].lower(),
            'nodc_template_version attribute must be {}'.format(self.valid_templates[0])
        )
        required_ctx.assert_true(
            getattr(dataset, 'cdm_data_type', '') == 'Trajectory',
            'cdm_data_type attribute must be set to Trajectory'
        )
        required_ctx.assert_true(
            getattr(dataset, 'featureType', '') == 'trajectory',
            'featureType attribute must be set to trajectory'
        )
        results.append(required_ctx.to_result())
        return results
Пример #21
0
    def check_dimensions(self, dataset):
        """
        Checks that the feature types of this dataset are consitent with a point dataset
        """
        required_ctx = TestCtx(BaseCheck.HIGH, "All geophysical variables are point feature types")
        t = util.get_time_variable(dataset)

        # Exit prematurely
        if not t:
            required_ctx.assert_true(False, "A dimension representing time is required for point feature types")
            return required_ctx.to_result()
        t_dims = dataset.variables[t].dimensions
        o = None or (t_dims and t_dims[0])

        message = "{} must be a valid timeseries feature type. It must have dimensions of ({}), and all coordinates must have dimensions of ({})"
        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_point(dataset, variable)
            required_ctx.assert_true(is_valid, message.format(variable, o, o))
        return required_ctx.to_result()
Пример #22
0
    def check_dimensions(self, dataset):
        '''
        Checks that the feature types of this dataset are consitent with a point dataset
        '''
        required_ctx = TestCtx(
            BaseCheck.HIGH,
            'All geophysical variables are point feature types')
        t = util.get_time_variable(dataset)

        # Exit prematurely
        if not t:
            required_ctx.assert_true(
                False,
                'A dimension representing time is required for point feature types'
            )
            return required_ctx.to_result()
        t_dims = dataset.variables[t].dimensions
        o = None or (t_dims and t_dims[0])

        message = '{} must be a valid timeseries feature type. It must have dimensions of ({}), and all coordinates must have dimensions of ({})'
        for variable in util.get_geophysical_variables(dataset):
            is_valid = util.is_point(dataset, variable)
            required_ctx.assert_true(is_valid, message.format(variable, o, o))
        return required_ctx.to_result()
Пример #23
0
    def check_recommended_attributes(self, dataset):
        '''
        Feature type specific check of global recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        recommended_ctx = TestCtx(BaseCheck.MEDIUM, 'Recommended global attributes')
        # Check time_coverage_duration and resolution
        for attr in ['time_coverage_duration', 'time_coverage_resolution']:
            attr_value = getattr(dataset, attr, '')
            try:
                parse_duration(attr_value)
                recommended_ctx.assert_true(True, '')  # Score it True!
            except Exception:
                recommended_ctx.assert_true(False, '{} should exist and be ISO-8601 format (example: PT1M30S), currently: {}'.format(attr, attr_value))
        results.append(recommended_ctx.to_result())
        return results
Пример #24
0
    def check_recommended_attributes(self, dataset):
        '''
        Feature type specific check of global recommended attributes.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        recommended_ctx = TestCtx(BaseCheck.MEDIUM,
                                  'Recommended global attributes')
        # Check time_coverage_duration and resolution
        for attr in ['time_coverage_duration', 'time_coverage_resolution']:
            attr_value = getattr(dataset, attr, '')
            try:
                parse_duration(attr_value)
                recommended_ctx.assert_true(True, '')  # Score it True!
            except Exception:
                recommended_ctx.assert_true(
                    False,
                    '{} should exist and be ISO-8601 format (example: PT1M30S), currently: {}'
                    .format(attr, attr_value))
        results.append(recommended_ctx.to_result())
        return results
Пример #25
0
    def check_trajectory_id(self, dataset):
        '''
        Checks that if a variable exists for the trajectory id it has the appropriate attributes

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        exists_ctx = TestCtx(BaseCheck.MEDIUM,
                             'Variable defining "trajectory_id" exists')
        trajectory_ids = dataset.get_variables_by_attributes(
            cf_role='trajectory_id')
        # No need to check
        exists_ctx.assert_true(
            trajectory_ids, 'variable defining cf_role="trajectory_id" exists')
        if not trajectory_ids:
            return exists_ctx.to_result()
        results.append(exists_ctx.to_result())
        test_ctx = TestCtx(
            BaseCheck.MEDIUM,
            'Recommended attributes for the {} variable'.format(
                trajectory_ids[0].name))
        test_ctx.assert_true(
            getattr(trajectory_ids[0], 'long_name', '') != "",
            "long_name attribute should exist and not be empty")
        results.append(test_ctx.to_result())
        return results
Пример #26
0
    def check_timeseries_id(self, dataset):
        '''
        Checks that if a variable exists for the time series id it has the appropriate attributes

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        results = []
        required_ctx = TestCtx(BaseCheck.HIGH,
                               'Required variable for time series identifier')
        recommended_ctx = TestCtx(
            BaseCheck.MEDIUM,
            'Recommended attributes for the timeSeries variable')
        # A variable with cf_role="timeseries_id" MUST exist for this to be a valid timeseries incomplete
        timeseries_ids = dataset.get_variables_by_attributes(
            cf_role='timeseries_id')
        required_ctx.assert_true(
            timeseries_ids,
            'a unique variable must define attribute cf_role="timeseries_id"')
        results.append(required_ctx.to_result())
        if not timeseries_ids:
            return results

        timevar = util.get_time_variable(dataset)
        nc_timevar = dataset.variables[timevar]
        time_dimensions = nc_timevar.dimensions

        timeseries_variable = timeseries_ids[0]
        dims = timeseries_variable.dimensions
        required_ctx.assert_true(
            time_dimensions and time_dimensions[0] == dims[0],
            '{} must have a dimension and that dimension must be shared by the time variable'
            .format(timeseries_variable.name))
        recommended_ctx.assert_true(
            getattr(timeseries_variable, 'long_name', '') != "",
            "long_name attribute should exist and not be empty")
        results.append(recommended_ctx.to_result())
        return results
Пример #27
0
    def check_bounds_variables(self, dataset):
        '''
        Checks the grid boundary variables.

        :param netCDF4.Dataset dataset: An open netCDF dataset
        '''
        recommended_ctx = TestCtx(
            BaseCheck.MEDIUM,
            'Recommended variables to describe grid boundaries')

        bounds_map = {
            'lat_bounds': {
                'units':
                'degrees_north',
                'comment':
                'latitude values at the north and south bounds of each pixel.'
            },
            'lon_bounds': {
                'units':
                'degrees_east',
                'comment':
                'longitude values at the west and east bounds of each pixel.'
            },
            'z_bounds': {
                'comment': 'z bounds for each z value',
            },
            'time_bounds': {
                'comment': 'time bounds for each time value'
            }
        }

        bounds_variables = [
            v.bounds for v in dataset.get_variables_by_attributes(
                bounds=lambda x: x is not None)
        ]

        for variable in bounds_variables:
            ncvar = dataset.variables.get(variable, {})
            recommended_ctx.assert_true(
                ncvar != {},
                'a variable {} should exist as indicated by a bounds attribute'
                .format(variable))
            if ncvar == {}:
                continue

            units = getattr(ncvar, 'units', '')
            if variable in bounds_map and 'units' in bounds_map[variable]:
                recommended_ctx.assert_true(
                    units == bounds_map[variable]['units'],
                    'variable {} should have units {}'.format(
                        variable, bounds_map[variable]['units']))
            else:
                recommended_ctx.assert_true(
                    units != '',
                    'variable {} should have a units attribute that is not empty'
                    .format(variable))

            comment = getattr(ncvar, 'comment', '')
            recommended_ctx.assert_true(
                comment != '',
                'variable {} should have a comment and not be empty')

        return recommended_ctx.to_result()