def check_lon_extents(self, ds):
        '''
        Check that the values of geospatial_lon_min/geospatial_lon_max
        approximately match the data.

        :param netCDF4.Dataset ds: An open netCDF dataset
        '''

        if not (hasattr(ds, 'geospatial_lon_min') and hasattr(ds, 'geospatial_lon_max')):
            return Result(BaseCheck.MEDIUM,
                          False,
                          'geospatial_lon_extents_match',
                          ['geospatial_lon_min/max attribute not found, CF-1.6 spec chapter 4.1'])

        try: # type cast
            lon_min = float(ds.geospatial_lon_min)
            lon_max = float(ds.geospatial_lon_max)
        except ValueError:
            return Result(BaseCheck.MEDIUM,
                          False,
                          'geospatial_lon_extents_match',
                          ['Could not convert one of geospatial_lon_min ({}) or max ({}) to float see CF-1.6 spec chapter 4.1'
                          ''.format(ds.geospatial_lon_min, ds.geospatial_lon_max)])

        # identify lon var(s) as per CF 4.2
        lon_vars = {}       # var -> number of criteria passed
        for name, var in ds.variables.items():

            # must have units
            if not hasattr(var, 'units'):
                continue

            lon_vars[var] = 0

            # units in this set
            if var.units in _possiblexunits:
                lon_vars[var] += 1

            # standard name of "longitude"
            if hasattr(var, 'standard_name') and var.standard_name == 'longitude':
                lon_vars[var] += 1

            # axis of "Y"
            if hasattr(var, 'axis') and var.axis == 'X':
                lon_vars[var] += 1

        # trim out any zeros
        lon_vars = {k: v for k, v in lon_vars.items() if v > 0}

        if len(lon_vars) == 0:
            return Result(BaseCheck.MEDIUM,
                          False,
                          'geospatial_lon_extents_match',
                          ['Could not find lon variable to test extent of geospatial_lon_min/max, see CF-1.6 spec chapter 4.2'])

        # sort by criteria passed
        final_lons = sorted(lon_vars, key=lambda x: lon_vars[x], reverse=True)

        obs_mins = {var._name: np.nanmin(var) for var in final_lons if not np.isnan(var).all()}
        obs_maxs = {var._name: np.nanmax(var) for var in final_lons if not np.isnan(var).all()}

        min_pass = any((np.isclose(lon_min, min_val) for min_val in obs_mins.values()))
        max_pass = any((np.isclose(lon_max, max_val) for max_val in obs_maxs.values()))

        allpass = sum((min_pass, max_pass))

        msgs = []
        if not min_pass:
            msgs.append("Data for possible longitude variables (%s) did not match geospatial_lon_min value (%s)" % (obs_mins, lon_min))
        if not max_pass:
            msgs.append("Data for possible longitude variables (%s) did not match geospatial_lon_max value (%s)" % (obs_maxs, lon_max))

        return Result(BaseCheck.MEDIUM,
                      (allpass, 2),
                      'geospatial_lon_extents_match',
                      msgs)
def check_lon_extents ( self , ds ) : if not ( hasattr ( ds , 'geospatial_lon_min' ) and hasattr ( ds , 'geospatial_lon_max' ) ) : return Result ( BaseCheck . MEDIUM , False , 'geospatial_lon_extents_match' , [ 'geospatial_lon_min/max attribute not found, CF-1.6 spec chapter 4.1' ] ) try : lon_min = float ( ds . geospatial_lon_min ) lon_max = float ( ds . geospatial_lon_max ) except ValueError : return Result ( BaseCheck . MEDIUM , False , 'geospatial_lon_extents_match' , [ 'Could not convert one of geospatial_lon_min ({}) or max ({}) to float see CF-1.6 spec chapter 4.1' '' . format ( ds . geospatial_lon_min , ds . geospatial_lon_max ) ] ) lon_vars = { } for name , var in ds . variables . items ( ) : if not hasattr ( var , 'units' ) : continue lon_vars [ var ] = 0 if var . units in _possiblexunits : lon_vars [ var ] += 1 if hasattr ( var , 'standard_name' ) and var . standard_name == 'longitude' : lon_vars [ var ] += 1 if hasattr ( var , 'axis' ) and var . axis == 'X' : lon_vars [ var ] += 1 lon_vars = { k : v for k , v in lon_vars . items ( ) if v > 0 } if len ( lon_vars ) == 0 : return Result ( BaseCheck . MEDIUM , False , 'geospatial_lon_extents_match' , [ 'Could not find lon variable to test extent of geospatial_lon_min/max, see CF-1.6 spec chapter 4.2' ] ) final_lons = sorted ( lon_vars , key = lambda x : lon_vars [ x ] , reverse = True ) obs_mins = { var . _name : np . nanmin ( var ) for var in final_lons if not np . isnan ( var ) . all ( ) } obs_maxs = { var . _name : np . nanmax ( var ) for var in final_lons if not np . isnan ( var ) . all ( ) } min_pass = any ( ( np . isclose ( lon_min , min_val ) for min_val in obs_mins . values ( ) ) ) max_pass = any ( ( np . isclose ( lon_max , max_val ) for max_val in obs_maxs . values ( ) ) ) allpass = sum ( ( min_pass , max_pass ) ) msgs = [ ] if not min_pass : msgs . append ( "Data for possible longitude variables (%s) did not match geospatial_lon_min value (%s)" % ( obs_mins , lon_min ) ) if not max_pass : msgs . append ( "Data for possible longitude variables (%s) did not match geospatial_lon_max value (%s)" % ( obs_maxs , lon_max ) ) return Result ( BaseCheck . MEDIUM , ( allpass , 2 ) , 'geospatial_lon_extents_match' , msgs )
Check that the values of geospatial_lon_min/geospatial_lon_max
        approximately match the data.

        :param netCDF4.Dataset ds: An open netCDF dataset