Interpolating
Overview
Teaching: 0 min
Exercises: 0 minQuestions
How do I interpolate data to a different grid
Objectives
It is common in climate data analysis to need to interpolate data to a different grid. One example is that I have model data on a model grid and observed data on a different grid. I want to calculate a difference between model and obs.
In this lesson, We will make a difference between the average SST in a CMIP5 model historical simulation and the average observed SSTs from the OISSTv2 dataset we have been working with.
Regular Grid
If you are using a regular grid, interpolation is easy using xarray
.
A regular grid is one with a 1-dimensional latitude and 1-dimensional longitude. This means that the latitudes are the same for all longitudes and the longitudes are the same for all latitudes.
Most data you encounter will be on a regular grid, but some are not. We will discuss irregular grids in another class.
First Steps
Create a new notebook and save it as Interpolating.ipynb.
Import the standard set of packages we use:
import xarray as xr
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
Read in obs and mask data:
obs_file='/shared/obs/gridded/OISSTv2/monthly/sst.mnmean.nc'
ds_obs=xr.open_dataset(data_file)
ds_obs
mask_file='/shared/obs/gridded/OISSTv2/lmask/lsmask.nc'
ds_mask=xr.open_dataset(mask_file)
ds_mask
This is the original data file we read in and land/sea mask we previously used.
Remember, we want to reverse the lats
ds_mask=ds_mask.reindex(lat=list(reversed(ds_mask['lat'])))
ds_obs=ds_obs.reindex(lat=list(reversed(ds_obs['lat'])))
plt.contourf(ds_obs['sst'][0,:,:])
Read in the model data
model_path='/shared/cmip5/data/historical/atmos/mon/Amon/ts/NCAR.CCSM4/r1i1p1/'
model_file='ts_Amon_CCSM4_historical_r1i1p1_185001-200512.nc'
ds_model=xr.open_dataset(model_path+model_file)
ds_model
This data has lats from S to N, so we don’t need to reverse it. Take a look at our model data. This data appears to have different units than the obs data.
We can change this.
ds_model['ts']=ds_model['ts']-273.15
Remember that xarray
keeps our metadata with our data, so we need to also change the metadata to keep that information correct in our xarray.Dataset
ds_model['ts'].attrs['units']=ds_obs['sst'].attrs['units']
How would you take the time mean of each dataset?
ds_model_mean=ds_model.mean(dim='time')
ds_obs_mean=ds_obs.mean(dim='time')
ds_model_mean
We are now going to use the interp_like
function. The documentation tells us that this fucntion interpolates an object onto the coordinates of another object, filling out of range values with NaN
.
One important thing to know that is not clear in the documentation is that the coordinates and variable name to interpolate must all be the same.
All variables in the Dataset
that have the same name as the one we are interpolating to will be interpolated.
Both of our datasets use lat and lon, but the model dataset uses ts
and the obs dataset uses sst
. Let’s change the name of the model variable to sst
.
ds_model_mean=ds_model_mean.rename({'ts':'sst'})
We will interpolate the model to be like the obs.
model_interp=ds_model_mean.interp_like(ds_obs_mean)
model_interp
Let’s take a look and compare with our data before interpolation.
plt.contourf(model_interp['sst'],cmap='coolwarm')
plt.title('Interpolated')
plt.colorbar()
plt.contourf(ds_model_mean['sst'],cmap='coolwarm')
plt.title('Original')
plt.colorbar()
Now let’s see how different our model mean is from the obs mean. Remember to apply our land/ocean mask.
diff=(model_interp-ds_obs_mean).where(ds_mask['mask'].squeeze()==1)
diff
And plot it…
plt.title('Model - OBS')
plt.contourf(diff['sst'], cmap='coolwarm')
plt.colorbar()
Key Points