Calculating wind fetch on lakes using Python
Wind traveling across water surfaces creates waves. Wave action depends on several parameters including fetch which is the unobstructed length which the wind can travel across a water surface from a given direction. Areas with high wind fetch are often exposed areas but this also depends on the primary wind direction. By calculating wind fetch, we can quantify exposure of different areas and shorelines in waterbodies. To my work, wind fetch is interesting from a physical perspective because it drives air-water gas exchange. However, it may also be interesting from an ecological viewpoint as wave exposure affects species distribution of submerged aquatic plants for example.
To calculate fetch, I have used the waver R-package which requires a point and polygon for the calculation. However, I did not find a suitable tool when dealing with lake rasters where I wanted fetch length for each raster cell. For this kind of application, vectorizing a raster to points, calculating fetch and rasterizing the points back to a raster was slow. Tools for this exist for ArcGIS which was not an option. In the end I decided it to use the opportunity to do some work in Python and created a useful and extendable interface along with a command-line tool.
It is available on Github. A script with the class, methods and functions doing the work, a script for exercising theme and a command-line tool.
The program
The program is kept simple for now but designed to be extensible for wave modeling for example. The example illustrates usage for a lake, however it can be used for all types of waterbodies. When importing data, a water-id value is supplied to separate water and land. Fetch lengths are calculated from top to bottom for regular sized arrays. In turn, lengths are calculated for each supplied direction by rotating the array. In addition to producing rasters with the fetch distance only along a single direction, a smoothed fetch raster may also be created by specifying a number of minor directions centered around this direciton by a given minor distance (see also example in the repository). Furthermore, summary statistics can be calculated for a stack of fetch rasters and weighting of fetch directions are also implemented.
The program relies on some Python libraries to be installed. Rasterio/GDAL is used for import and export, Numpy/SciPy for array handling. A suitable environment can quickly be set up using Anaconda.
Usage
For now, the program is a Python script which can be imported and used. The following examples assume you work in the same directory where the scripts are.
An example of a Python workflow:
from WindFetch import Waterbody, Fetch
import gdal
import matplotlib.pyplot as plt
import numpy as np
#Run test of fetch functions
#Danish lake Gurre (source: OpenStreetMap) attached as .sqlite file in projected crs
lake_vec = "test_files/gurre_lake"
#Rasterize vector file using gdal
lake_rast = gdal.Rasterize(lake_vec+".tif", lake_vec+".sqlite", xRes = 5, yRes = 5, burnValues = [1], noData = 0, outputType = gdal.GDT_Byte, creationOptions = ["COMPRESS=LZW"], )
lake_rast = None
#Read lake from .tif file
lake = Waterbody.read_waterbody(lake_vec+".tif", 1)
dirs = [0, 45, 90, 135, 180, 225, 270, 315]
#Fetch along main directions
fetch_main = lake.fetch(dirs)
#Summary statistics of calculated fetches
fetch_main_summary = fetch_main.summary(["min", "mean", "max"])
#Apply weighting to each direction
dirs_weights = [0.1, 0.3, 0.1, 0.2, 0, 0, 0.2, 0.1]
fetch_main_weight = fetch_main.weighting(dirs_weights)
#Calculated weighted mean
fetch_main_weight_mean = fetch_main_weight.summary(["mean"])
#Fetch along main directions each calculated as the average of 5 directions with a distance of 3 degrees
fetch_minor = lake.fetch(dirs, minor_directions = 5, minor_interval = 3)
#Write to file
fetch_minor.write_waterbody(lake_vec+"_fetch_minor.tif")
The resulting rasters containing fetch length for each cell and direction are visualized below using Leaflet. Explore the interactive map and use the box to show/hide the raster layers, notice how islands create shelter and “reset” the fetch. The sheltering affects the influence of wind and wave action.