html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,performed_via_github_app,issue https://github.com/pydata/xarray/issues/2037#issuecomment-1063808399,https://api.github.com/repos/pydata/xarray/issues/2037,1063808399,IC_kwDOAMm_X84_aG2P,40183561,2022-03-10T08:46:31Z,2022-03-10T08:46:31Z,CONTRIBUTOR,"@BorjaEst I don't think I ever pushed anything up, sorry. Probably best to start a new one.","{""total_count"": 1, ""+1"": 1, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,310833761 https://github.com/pydata/xarray/issues/2037#issuecomment-1063784085,https://api.github.com/repos/pydata/xarray/issues/2037,1063784085,IC_kwDOAMm_X84_aA6V,40183561,2022-03-10T08:14:59Z,2022-03-10T08:14:59Z,CONTRIBUTOR,@BorjaEst I haven't opened a PR for this 🙂 ,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,310833761 https://github.com/pydata/xarray/issues/2037#issuecomment-857563427,https://api.github.com/repos/pydata/xarray/issues/2037,857563427,MDEyOklzc3VlQ29tbWVudDg1NzU2MzQyNw==,40183561,2021-06-09T10:03:22Z,2021-06-10T12:39:04Z,CONTRIBUTOR,"I had a go at working on this, as mentioned in #5448 it could be a fix in https://github.com/pydata/xarray/blob/ce01f42134962b63d453657c5cb649ebf152283d/xarray/conventions.py#L707 I couldn't see how to fix it in there but tried a fix at the end of https://github.com/pydata/xarray/blob/ce01f42134962b63d453657c5cb649ebf152283d/xarray/conventions.py#L813 for bounds and coordinate variables. See below: ```python def cf_encoder(variables, attributes): """""" Encode a set of CF encoded variables and attributes. Takes a dicts of variables and attributes and encodes them to conform to CF conventions as much as possible. This includes masking, scaling, character array handling, and CF-time encoding. Parameters ---------- variables : dict A dictionary mapping from variable name to xarray.Variable attributes : dict A dictionary mapping from attribute name to value Returns ------- encoded_variables : dict A dictionary mapping from variable name to xarray.Variable, encoded_attributes : dict A dictionary mapping from attribute name to value See Also -------- decode_cf_variable, encode_cf_variable """""" # add encoding for time bounds variables if present. _update_bounds_encoding(variables) new_vars = {k: encode_cf_variable(v, name=k) for k, v in variables.items()} # Remove attrs from bounds variables (issue #2921) for var in new_vars.values(): bounds = var.attrs[""bounds""] if ""bounds"" in var.attrs else None if bounds and bounds in new_vars: # see http://cfconventions.org/cf-conventions/cf-conventions.html#cell-boundaries for attr in [ ""units"", ""standard_name"", ""axis"", ""positive"", ""calendar"", ""long_name"", ""leap_month"", ""leap_year"", ""month_lengths"", ]: if attr in new_vars[bounds].attrs and attr in var.attrs: if new_vars[bounds].attrs[attr] == var.attrs[attr]: new_vars[bounds].attrs.pop(attr) # remove _FillValue for bounds if new_vars[bounds].attrs.get(""_FillValue""): new_vars[bounds].attrs[""_FillValue""] = None # remove _FillValue for coordinate variables as missing values are not permitted # a coordinate variable is a one-dimensional variable with the same name as its dimension # see coordinate variable in http://cfconventions.org/cf-conventions/cf-conventions.html#terminology for var in new_vars.keys(): if new_vars[var].dims == (var,) and new_vars[var].attrs.get(""_FillValue""): new_vars[var].attrs[""_FillValue""] = None return new_vars, attributes ``` tests to add into `test_conventions.py` could be something like: ```python def test_fill_value_none_for_coordinate_variables(): # need to be floats so _FillValue is added temp = 273.15 + 25 * np.random.randn(2, 2) lon = [0.0, 5.0] lat = [10.0, 20.0] ds = Dataset({'temperature': (['lat', 'lon'], temp)}, coords={'lat': lat, 'lon': lon}) ds['lat'].attrs = { 'standard_name': 'latitude', 'long_name': 'latitude', 'units': 'degrees_north', 'axis': 'Y'} ds['lon'].attrs = { 'standard_name': 'longitude', 'long_name': 'longitude', 'units': 'degrees_east', 'axis': 'X'} ds['temperature'].attrs = { 'standard_name': 'air_temperature', 'units': 'K'} v, _ = conventions.cf_encoder(ds.variables, ds.attrs) assert v[""lat""].attrs['_FillValue'] is None assert v[""lon""].attrs['_FillValue'] is None # check _FillValue still inserted for temperature assert v[""temperature""].attrs['_FillValue'] is not None def test_fill_value_none_for_bounds_variables(): # need to be floats so _FillValue is added temp = 273.15 + 25 * np.random.randn(2, 2) lat_bnds = np.arange(4.0).reshape((2, 2)) lon = [0.0, 5.0] lat = [10.0, 20.0] ds = Dataset({'temperature': (['lat', 'lon'], temp), 'lat_bnds': (['lat', 'nbnds'], lat_bnds), 'lon_bnds': (['lon', 'nbnds'], lat_bnds)}, coords={'lat': lat, 'lon': lon}) ds['lat'].attrs = { 'standard_name': 'latitude', 'long_name': 'latitude', 'units': 'degrees_north', 'axis': 'Y', 'bounds': 'lat_bnds'} ds['lon'].attrs = { 'standard_name': 'longitude', 'long_name': 'longitude', 'units': 'degrees_east', 'axis': 'X', 'bounds': 'lon_bnds'} ds['temperature'].attrs = { 'standard_name': 'air_temperature', 'units': 'K'} v, _ = conventions.cf_encoder(ds.variables, ds.attrs) assert v[""lat_bnds""].attrs['_FillValue'] is None assert v[""lon_bnds""].attrs['_FillValue'] is None ``` but I couldn't quite get this to work, with some tests in `test_backends.py` failing. I could see that the fill value is being added in by `maybe_default_fill_value` in `conventions.py` so maybe it would be better to skip coordinate variable and bounds here. I can't really spend anymore time on this but putting it here in case its useful.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,310833761