How to use a binary netcdf mask in python?

Viewed 265

Im fairly new to using the cartopy package. I wanted to use a land sea mask from a given binary map in netcdf format. Here lsm_set is my netcdf file that contains that binary map and t2m_set is the data that I'd like to map. I'm still playing around with cartopy a little bit to get the hang of it, but I can't seem to figure out how to use the land sea mask. I've read several related questions here, but they didn't work on my code because my t2m variables did not have the attribute mask.

My teacher said I could use it to mark the sea values as "NaN" but I didn't know an efficient way to do it. I tried it with a while loop but that's super slow when you're working with this much data :')

I used data found from the copernicus institute on the following link: https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-uerra-europe-single-levels?tab=form

import os
import numpy as np
import matplotlib.pyplot as plt
import netCDF4 as nc
from netCDF4 import Dataset
import xarray as xr
from cartopy import config
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader


filepath1 = '... file path... '
lsm_set = xr.open_dataset(filepath1)

filepath2 = '... file path...'
t2m_set= xr.open_dataset(filepath2) 

lons = lsm_set.variables['longitude']#[:]
lats = lsm_set.variables['latitude']#[:]
lsm = lsm_set.variables['lsm']
t2m = t2m_set.variables['t2m']

plt.figure(figsize=(8, 8))
ax = plt.axes(projection = ccrs.Mercator())
ax.contourf(lons[200:400,100:300], lats[100:300,200:400], t2m[100:300,100:300],transform=ccrs.Mercator())
lsm_set.close()
t2m_set.close()
plt.show()

Any nudge in the right direction is appreciated, thanks!


Solved!

Turns out the solution was a lot easier than I thought.

lons = t2m_set.variables['longitude']#[:]
lats = t2m_set.variables['latitude']#[:]
lsm = lsm_set.variables['lsm']
t2m = t2m_set.variables['t2m'] 
lsm_masked = lsm.where(lsm!=0.)
mapdata = t2m+lsm_masked

And than plot mapdata instead of just t2m

2 Answers

You could use the where method of xarray :

t2m_set.where(lsm_set)

It should give you a nicely masked xarray.Dataset.

Let me assume you have the land/sea data as 1's and 0's and the same size as your data... Then you can easily make a plot like this:

#!/usr/bin/env ipython
# --------------------
import matplotlib as mpl
mpl.rcParams['font.size'] = 18
import matplotlib.pylab as plt
import numpy as np
# -----------------------------
xx = np.linspace(9.,30,100);
yy = np.linspace(54.0,66.0,100);
xm,ym = np.meshgrid(xx,yy);
zz = 50.0 + 10.0*np.random.random((np.size(yy),np.size(xx)));
# -----------------------------
# let me have some random landmask/seamask data:
smask = np.zeros(np.shape(zz));smask[0:10,0:10]=1.0;smask[60:90,60:90]=1.0;
# -----------------------------
# let us set 0.0 to NaNs in seamask:
smask[smask==0]=np.nan;
smask=np.ma.array(smask,mask=np.isnan(smask))
# -----------------------------
# let us make a plot:
fig = plt.figure();ax=fig.add_subplot(111);
ax.pcolormesh(xx,yy,zz);
ax.pcolormesh(xx,yy,smask,vmin=0.0,vmax=8.0,cmap='Greys');
plt.show()
# ------------------------------------------------------------
Related