%matplotlib inline
from netCDF4 import Dataset
import wrf
import xarray as xr
import numpy as np
import cartopy.crs as crs
root_dir = '/data/fiss_aic/WRF/runA_2010'
nc = Dataset(root_dir+'/wrfout_d02_2010-03-18_00:00:00')
e.g., where your lat/lon coordinates are stored in another file
In this example we will extract infomation from two netCDF files (src + coord_file) and add to an empty netCDF Dataset (dst)
root_dir = '/data/fiss_aic/WRF/runA_2010'
my_vars = ['SPDUV10MEAN', 'V10MEAN', 'U10MEAN']
#################################
### Get variables and dimensions
#################################
### source
src = Dataset(root_dir+'/wrfxtrm_d02')
### destination (tmp netCDF file stored in memory) - close first if exists
### close in-memory netCDF Dataset (if exists)
try:
print('>> closing dst << \n')
dst.close()
except NameError:
pass
dst = Dataset("dst_tmp.nc", "w", format="NETCDF4", diskless=True)
### copy netCDF attributes from source file to destination file
dst.setncatts(src.__dict__)
### copy all dimensions from src to dst
for name, dimension in src.dimensions.items():
dst.createDimension(name,
len(dimension) if not dimension.isunlimited() else None)
>> closing dst <<
#################################
### Add time coordinates
#################################
name = 'Times'
variable = src.variables[name]
dst.createVariable(name, variable.datatype, variable.dimensions)
dst.variables[name][:] = src.variables[name][:]
dst[name].setncatts(src[name].__dict__)
#################################
### Add lat/lon coordinates
#################################
coord_file = Dataset(root_dir+'/wrfout_d02_2010-03-18_00:00:00')
coords = ['XLAT', 'XLONG']
for name in coords:
variable = coord_file.variables[name]
dst.createVariable(name, variable.datatype, variable.dimensions)
### create coord array with the correct shape (i.e. lat x lon for all times)
correct_shape_arr = np.zeros( dst.variables[name].shape )
correct_shape_arr[:,:,:] = coord_file.variables[name][0,:,:]
dst.variables[name][:] = correct_shape_arr
dst[name].setncatts(coord_file[name].__dict__)
#################################
### Extract any useful information
### from nc file
#################################
nx = dst.dimensions['west_east'].size
ny = dst.dimensions['south_north'].size
dt, dx, dy = dst.DT, dst.DX, dst.DY
cen_lat, cen_lon = dst.CEN_LAT, dst.CEN_LON
truelat1, truelat2, STAND_LON = dst.TRUELAT1, dst.TRUELAT2, dst.STAND_LON
pole_lat, pole_lon = dst.POLE_LAT, dst.POLE_LON
#################################
### Add south_north and west_east - NOT NEEDED BY WRF-PYTHON
#################################
x0_y0 = wrf.get_cartopy(wrfin=dst).transform_point( dst.variables['XLONG'][0,0,0],
dst.variables['XLAT'][0,0,0],
crs.PlateCarree())
west_east_points = np.arange(nx, dtype='float32') * dy + x0_y0[0]
south_north_points = np.arange(ny, dtype='float32') * dy + x0_y0[1]
### Create nc variable
dst.createVariable('south_north', south_north_points.dtype, ('south_north') )
dst.variables['south_north'][:] = south_north_points
dst['south_north'].setncatts( {'units':'m', 'axis':'y'} )
dst.createVariable('west_east', west_east_points.dtype, ('west_east') )
dst.variables['west_east'][:] = west_east_points
dst['west_east'].setncatts( {'units':'m', 'axis':'x'} )
#################################
### copy chosen variables (my_var)
### from src to dst
#################################
for name in list(my_vars):
variable = src.variables[name]
dst.createVariable(name, variable.datatype, variable.dimensions)
dst.variables[name][:] = src.variables[name][:]
dst[name].setncatts(src[name].__dict__)
### create list of variables in the Xarray DataArray format
da_list = []
for my_var in my_vars:
da_list.append( wrf.getvar(dst, my_var, timeidx=wrf.ALL_TIMES) )
### merge all variables (Xarray DataArrays) into one Xarray Dataset
ds = xr.merge(da_list)
### Show me a summary of the Dataset...
ds
<xarray.Dataset> Dimensions: (Time: 380, south_north: 201, west_east: 147) Coordinates: XLONG (south_north, west_east) float32 -123.254684 ... -28.57109 XLAT (south_north, west_east) float32 -78.73641 ... -60.162468 * Time (Time) datetime64[ns] 2010-03-18 2010-03-19 ... 2011-04-01 Dimensions without coordinates: south_north, west_east Data variables: SPDUV10MEAN (Time, south_north, west_east) float32 0.0 0.0 ... 11.252552 V10MEAN (Time, south_north, west_east) float32 0.0 0.0 ... 8.698959 U10MEAN (Time, south_north, west_east) float32 0.0 0.0 ... -6.9788127
### close in-memory netCDF Dataset (if exists)
try:
print('>> closing dst << \n')
dst.close()
except NameError:
pass
>> closing dst <<
ds.to_netcdf('test.nc')
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-12-5c431fe9edba> in <module>() ----> 1 ds.to_netcdf('test.nc') /data/clivarm/wip/jask/miniconda3/lib/python3.6/site-packages/xarray/core/dataset.py in to_netcdf(self, path, mode, format, group, engine, encoding, unlimited_dims, compute) 1252 engine=engine, encoding=encoding, 1253 unlimited_dims=unlimited_dims, -> 1254 compute=compute) 1255 1256 def to_zarr(self, store=None, mode='w-', synchronizer=None, group=None, /data/clivarm/wip/jask/miniconda3/lib/python3.6/site-packages/xarray/backends/api.py in to_netcdf(dataset, path_or_file, mode, format, group, engine, writer, encoding, unlimited_dims, compute) 686 # validate Dataset keys, DataArray names, and attr keys/values 687 _validate_dataset_names(dataset) --> 688 _validate_attrs(dataset) 689 690 try: /data/clivarm/wip/jask/miniconda3/lib/python3.6/site-packages/xarray/backends/api.py in _validate_attrs(dataset) 118 for variable in dataset.variables.values(): 119 for k, v in variable.attrs.items(): --> 120 check_attr(k, v) 121 122 /data/clivarm/wip/jask/miniconda3/lib/python3.6/site-packages/xarray/backends/api.py in check_attr(name, value) 109 'string, ndarray or a list/tuple of ' 110 'numbers/strings for serialization to netCDF ' --> 111 'files'.format(value)) 112 113 # Check attrs on the dataset itself TypeError: Invalid value for attr: PolarStereographic(stand_lon=-45.0, moad_cen_lat=-75.49999237060547, truelat1=-90.0, truelat2=-90.0, pole_lat=90.0, pole_lon=0.0) must be a number string, ndarray or a list/tuple of numbers/strings for serialization to netCDF files
ds['SPDUV10MEAN'].attrs
OrderedDict([('FieldType', 104), ('MemoryOrder', 'XY '), ('description', 'MEAN WIND SPEED AT 10M HEIGHT IN DIAGNOSTIC OUTPUT INTERVAL'), ('units', 'm s-1'), ('stagger', ''), ('coordinates', 'XLONG XLAT XTIME'), ('projection', PolarStereographic(stand_lon=-45.0, moad_cen_lat=-75.49999237060547, truelat1=-90.0, truelat2=-90.0, pole_lat=90.0, pole_lon=0.0))])
### Fix attributes so that we can save to file...
for my_var in my_vars:
ds[my_var].attrs['projection'] = str(ds[my_var].attrs['projection'])
ds[my_var].attrs.pop('coordinates')
ds.to_netcdf('test.nc')
### Success!!??
!ls -ltrh test.nc
-rw-r--r-- 1 jask psd 129M Feb 5 16:16 test.nc
ds2 = xr.open_dataset('test.nc')
ds2
<xarray.Dataset> Dimensions: (Time: 380, south_north: 201, west_east: 147) Coordinates: XLONG (south_north, west_east) float32 ... XLAT (south_north, west_east) float32 ... * Time (Time) datetime64[ns] 2010-03-18 2010-03-19 ... 2011-04-01 Dimensions without coordinates: south_north, west_east Data variables: SPDUV10MEAN (Time, south_north, west_east) float32 ... V10MEAN (Time, south_north, west_east) float32 ... U10MEAN (Time, south_north, west_east) float32 ...
ds2['SPDUV10MEAN'].attrs
OrderedDict([('FieldType', 104), ('MemoryOrder', 'XY '), ('description', 'MEAN WIND SPEED AT 10M HEIGHT IN DIAGNOSTIC OUTPUT INTERVAL'), ('units', 'm s-1'), ('stagger', ''), ('projection', 'PolarStereographic(stand_lon=-45.0, moad_cen_lat=-75.49999237060547, truelat1=-90.0, truelat2=-90.0, pole_lat=90.0, pole_lon=0.0)')])