Create AMM7 masks from shapefiles

Use DEFRA's CP2 regions in shapefiles to create NEMO AMM7 raster masks and save into a netCDF file.

Table of Contents


In [37]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')



In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
import cartopy
import cartopy.crs as ccrs
import numpy as np
import xarray as xr
import math

In [2]:
amm7ds = xr.open_dataset('data/amm7_subdomains_v2.nc')

cp2_lv1_fname = 'data/CP2_lv1_v2.shp' # One region
cp2_lv2_fname = 'data/CP2_lv2_v2.shp' # UK shelf anf off shelf
cp2_lv3_fname = 'data/CP2_new_edit_v2.shp'# The complete 9 regions

Function definitions


In [3]:
def plot_shapefile(shapefile,extent_lonlat=[-16,6,46,65]):

    plt.figure(figsize=(4,4))

    crs_lambea = ccrs.LambertAzimuthalEqualArea(central_latitude=55.0)
    crs_lonlat = ccrs.PlateCarree()

    ax = plt.axes(projection=crs_lambea)

    xmin, ymin = crs_lambea.transform_point(extent_lonlat[0], extent_lonlat[2], crs_lonlat)
    xmax, ymax = crs_lambea.transform_point(extent_lonlat[1], extent_lonlat[3], crs_lonlat)
    extent_lambea = (xmin, xmax, ymin, ymax)
    ax.set_extent(extent_lambea,crs=crs_lambea)

    shape_feature = ShapelyFeature(shapefile.geometries(),
                                ccrs.PlateCarree(), edgecolor='black')
    ax.add_feature(shape_feature)#, facecolor='blue')
    ax.coastlines(resolution='10m')
    ax.gridlines()

In [47]:
# Plot facet-like all DataArrays in Dataset
def plot_ds(ds):

    nvars = len(ds.data_vars)
    nrows = math.ceil(math.sqrt(nvars))
    ncols = math.ceil(nvars/nrows)
    fig,axs = plt.subplots(nrows=nrows,ncols=ncols,figsize=(15,15),squeeze=False)
    for ind, varn in enumerate(ds.data_vars):
        data = ds[varn].values.squeeze()
        col = ind % ncols
        row = int((ind-col)/ncols)
        #print('plot_ds',nrows,ncols,row,col,ind)
        ax = axs[row,col].imshow(np.flipud(data))
        axs[row,col].set_title(varn)

In [5]:
#**********************************************
def make_mask(polygon,arrayX,arrayY):
#**********************************************

    [Nrows,Nlines] = arrayX.shape
    mask = np.ma.zeros([Nrows,Nlines],dtype=bool)

    start=time.time()
    for row in range(Nrows):
        for col in range(Nlines):
            x = arrayX[row,col]
            y = arrayY[row,col]
            p=shply.Point(x,y)
            if p.within(polygon):
                mask[row,col] = True
    stop=time.time()
    elapsed= stop-start
    elapseds="%.2f"%elapsed
    print('make_mask: ' + elapseds + ' s')

    return mask

In [40]:
# takes shpfile name and return list of raster masks

def shapefile2masks(shp_fname):
    
    shpread = shp.Reader(shp_fname)
    shapes = shpread.shapes()
    
    #shapefile has no useful records describing the polygon
    try:
        shprecords = shpread.records()
        #print('records:',shprecords)
        shprecs=[]
        for rec in shprecords:
            # record 0 is OBJECTID
            shprecs=rec.append(rec[0])
            
        #print('shprecs',shprecs)
    except:
        print('ERROR: no records in shapefile')

    masks = []
    for shape in shapes:
        #print(shape)
        points = shape.points
        poly = shply.Polygon(points)
        mask = make_mask(poly,long,latg)
        masks.append(mask)
    
    return masks

Read and plot shapefiles with Charting Progress 2 boundaries


In [6]:
import cartopy.io.shapereader as shpreader
from cartopy.feature import ShapelyFeature

In [7]:
shapefile = shpreader.Reader(cp2_lv1_fname)
plot_shapefile(shapefile,extent_lonlat=[-16,6,46,65])



In [8]:
shapefile = shpreader.Reader(cp2_lv2_fname)
plot_shapefile(shapefile,extent_lonlat=[-16,6,46,65])



In [9]:
shapefile = shpreader.Reader(cp2_lv3_fname)
plot_shapefile(shapefile,extent_lonlat=[-16,6,46,65])



In [10]:
import shapefile as shp
import shapely.geometry as shply
import time

In [11]:
long,latg = np.meshgrid(amm7ds['lon'], amm7ds['lat'])

Convert polygons into rasters


In [41]:
masks1 = shapefile2masks(cp2_lv1_fname)
masks2 = shapefile2masks(cp2_lv2_fname)
masks3 = shapefile2masks(cp2_lv3_fname)


make_mask: 8.59 s
make_mask: 2.25 s
make_mask: 1.93 s
make_mask: 7.46 s
make_mask: 1.86 s
make_mask: 1.76 s
make_mask: 1.80 s
make_mask: 1.67 s
make_mask: 1.80 s
make_mask: 1.89 s
make_mask: 1.71 s
make_mask: 2.19 s
make_mask: 1.63 s
make_mask: 2.76 s

Save raster masks to netcdf


In [48]:
# Get coordinates from AMM7 domain file

lat = amm7ds['lat']
lon = amm7ds['lon']
llcoords = {'lat':lat,'lon':lon}
lldims = ('lat','lon')

Level 1


In [50]:
# Create Dataset with all masks and lat lon dimensions and save to netCDF

da0 = xr.DataArray(data=masks1[0],coords=llcoords,dims=lldims)
cp2_lv1_ds = xr.Dataset({'CP2_lv1':da0})

# Save to NetCDF file
#cp2_lv2_ds.to_netcdf('data/amm7_CP2_lv2.nc')

plot_ds(cp2_lv1_ds)


Level 2


In [51]:
# Create Dataset with all masks and lat lon dimensions and save to netCDF

print(len(masks2))
#plt.imshow(np.flipud(masks1[0]))

da0 = xr.DataArray(data=masks2[0],coords=llcoords,dims=lldims)
da1 = xr.DataArray(data=masks2[1],coords=llcoords,dims=lldims)
da2 = xr.DataArray(data=masks2[2],coords=llcoords,dims=lldims)
cp2_lv2_ds = xr.Dataset({'CP2_lv2_0':da0,'CP2_lv2_1':da1,'CP2_lv2_2':da2})

# Save to NetCDF file
#cp2_lv2_ds.to_netcdf('data/amm7_CP2_lv2.nc')

plot_ds(cp2_lv2_ds)


3

Load from file and test


In [52]:
fileds = xr.open_dataset('data/amm7_CP2_lv2.nc')
id0 = fileds['CP2_lv2_0']
id1 = fileds['CP2_lv2_1']
id2 = fileds['CP2_lv2_2']

In [53]:
# Combine polygons to test for overlap or gaps
fig = plt.figure( figsize=(10,10))
(id1+id0+id2).plot()


Out[53]:
<matplotlib.collections.QuadMesh at 0xdcf0ef0>

Level 3


In [58]:
# create Dataset with all masks and lat lon dimensions
# and save to netCDF

print(len(masks3))

da0 = xr.DataArray(data=masks3[0],coords=llcoords,dims=lldims)
da1 = xr.DataArray(data=masks3[1],coords=llcoords,dims=lldims)
da2 = xr.DataArray(data=masks3[2],coords=llcoords,dims=lldims)
da3 = xr.DataArray(data=masks3[3],coords=llcoords,dims=lldims)
da4 = xr.DataArray(data=masks3[4],coords=llcoords,dims=lldims)
da5 = xr.DataArray(data=masks3[5],coords=llcoords,dims=lldims)
da6 = xr.DataArray(data=masks3[6],coords=llcoords,dims=lldims)
da7 = xr.DataArray(data=masks3[7],coords=llcoords,dims=lldims)
da8 = xr.DataArray(data=masks3[8],coords=llcoords,dims=lldims)
da9 = xr.DataArray(data=masks3[9],coords=llcoords,dims=lldims)
cp2_lv3_ds = xr.Dataset({'Western Channel & Celtic Sea':da0,
                         'Eastern Channel':da1,
                         'Faroe-Shetland Channel':da2,
                         'Irish Sea':da3,'Minches & Western Scotland':da4,
                         'Northern North Sea':da5,
                         'Atlantic NW Approaches':da6,
                         'Rockall Trough & Bank':da7,
                         'Southern North Sea':da8,
                         'Scottish Continental Shelf':da9})

plot_ds(cp2_lv3_ds)

# Save to file
#cp2_lv3_ds.to_netcdf('data/amm7_CP2_lv3.nc')


10

Combine polygons to test for overlap or gaps


In [59]:
fig = plt.figure( figsize=(10,10))
(da1+da0+da2+da3+da4+da5+da6+da7+da8+da9).plot()


Out[59]:
<matplotlib.collections.QuadMesh at 0xea45c18>

Check file contents


In [16]:
fileds = xr.open_dataset('data/amm7_CP2_lv3.nc')
fileds
#id0 = fileds['CP2_lv2_0']
#id1 = fileds['CP2_lv2_1']
#id2 = fileds['CP2_lv2_2']


Out[16]:
<xarray.Dataset>
Dimensions:                       (lat: 375, lon: 297)
Coordinates:
  * lat                           (lat) float64 40.07 40.13 40.2 40.27 40.33 ...
  * lon                           (lon) float64 -19.89 -19.78 -19.67 -19.56 ...
Data variables:
    Western Channel & Celtic Sea  (lat, lon) bool ...
    Eastern Channel               (lat, lon) bool ...
    Faroe-Shetland Channel        (lat, lon) bool ...
    Irish Sea                     (lat, lon) bool ...
    Minches & Western Scotland    (lat, lon) bool ...
    Northern North Sea            (lat, lon) bool ...
    Atlantic NW Approaches        (lat, lon) bool ...
    Rockall Trough & Bank         (lat, lon) bool ...
    Southern North Sea            (lat, lon) bool ...
    Scottish Continental Shelf    (lat, lon) bool ...