JiaweiZhuang / xESMF

Universal Regridder for Geospatial Data
http://xesmf.readthedocs.io/
MIT License
269 stars 49 forks source link

keep_attrs doesn't keep attrs of coordinate variables #70

Open ahuang11 opened 4 years ago

ahuang11 commented 4 years ago
import xarray as xr
import numpy as np
import xesmf as xe

dims = ('time', 'lat', 'lon')
data = np.ones((1, 5, 7))
ds1 = xr.Dataset({
    'data': (dims, data),
    'time': [0],
    'lon': [0., 1., 2, 3, 4, 5, 358.],
    'lat': [-5, -6, -7, -8, -9]
})['data']
ds1.attrs['existed'] = 'ds'
ds1['lon'].attrs['existed'] = 'coord_var'

data = np.ones((1, 5, 5))
ds2 = xr.Dataset({
    'data': (dims, data),
    'time': [0],
    'lon': [0., 1., 2, 3, 4],
    'lat': [-5, -6, -7, -8, -9]
})['data']

ds1['lon']
regridder = xe.Regridder(ds1, ds2, method='bilinear')
regridder(ds1, keep_attrs=True)['lon']
<xarray.DataArray 'lon' (lon: 7)>
array([  0.,   1.,   2.,   3.,   4.,   5., 358.])
Coordinates:
  * lon      (lon) float64 0.0 1.0 2.0 3.0 4.0 5.0 358.0
Attributes:
    existed:  coord_var  # no longer here

<xarray.DataArray 'lon' (lon: 5)>
array([0., 1., 2., 3., 4.])
Coordinates:
  * lon      (lon) float64 0.0 1.0 2.0 3.0 4.0
JiaweiZhuang commented 4 years ago

keep_attrs only affects variable attributes, not coordinate attributes. This is the behavior of xarray.apply_ufunc(). I think this behavior makes sense, as the output lon is a different coordinate than the input lon, so they probably shouldn't share attributes.

On the other hand, the attributes of extra coordinates like time are always kept regardless of keep_attrs. This also makes sense as the input time and output time are exactly the same.

ahuang11 commented 4 years ago

But if I know both lons are in longitudinal degree and I set keep_attrs=True, I still want them to keep those units. Maybe keep_attrs can accept a str "all" to keep all attributes regardless.

JiaweiZhuang commented 4 years ago

I think it is good to be consistent with the kwargs in xarray.apply_ufunc and other xarray operations... For your case, you can setds_out['lon'].attrs['unit'] = 'degree'