H*Wind Analyses Using R

Here's a simple work-up showing how to load in NOAA/AOML H*Wind analysis data and display it. There is a lot of scientific opportunity from this data, and R's ability to model and handle space-time data makes this small exercise potentially very worthwhile.

First, we library in the R packages to help with handling spatial data and displaying it. The final goal in this exercise is an HTML animation.

library(rgdal)
## Loading required package: sp
## rgdal: version: 0.7.25, (SVN revision 400) Geospatial Data Abstraction
## Library extensions to R successfully loaded Loaded GDAL runtime: GDAL
## 1.9.0, released 2011/12/29 Path to GDAL shared files:
## /Library/Frameworks/R.framework/Versions/2.15/Resources/library/rgdal/gdal
## Loaded PROJ.4 runtime: Rel. 4.8.0, 6 March 2012, [PJ_VERSION: 480] Path to
## PROJ.4 shared files:
## /Library/Frameworks/R.framework/Versions/2.15/Resources/library/rgdal/proj
library(colorspace)
library(maps)
library(mapdata)
library(maptools)
## Loading required package: foreign
## Loading required package: grid
## Loading required package: lattice
## Checking rgeos availability: TRUE
library(animation)
library(lubridate)

Here are the urls for all analysese from Hurricane Katrina, available every 3 hours starting with its position just off the Florida coast (copying and pasting these URLs were the menial part of this exercise).

urls = c("ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0825/2100/AL122005_0825_2100shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/0000/AL122005_0826_0000shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/0300/AL122005_0826_0300shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/0600/AL122005_0826_0600shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/0900/AL122005_0826_0900shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/1200/AL122005_0826_1200shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/1500/AL122005_0826_1500shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/1800/AL122005_0826_1800shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0826/2100/AL122005_0826_2100shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/0000/AL122005_0827_0000shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/0300/AL122005_0827_0300shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/0600/AL122005_0827_0600shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/0900/AL122005_0827_0900shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/1200/AL122005_0827_1200shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/1500/AL122005_0827_1500shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/1800/AL122005_0827_1800shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0827/2100/AL122005_0827_2100shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/0000/AL122005_0828_0000shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/0300/AL122005_0828_0300shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/0600/AL122005_0828_0600shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/0900/AL122005_0828_0900shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/1200/AL122005_0828_1200shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/1500/AL122005_0828_1500shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/1800/AL122005_0828_1800shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0828/2100/AL122005_0828_2100shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/0000/AL122005_0829_0000shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/0300/AL122005_0829_0300shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/0600/AL122005_0829_0600shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/0900/AL122005_0829_0900shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/1200/AL122005_0829_1200shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/1500/AL122005_0829_1500shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/1800/AL122005_0829_1800shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0829/2100/AL122005_0829_2100shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0830/0000/AL122005_0830_0000shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0830/0300/AL122005_0830_0300shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0830/0600/AL122005_0830_0600shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0830/0900/AL122005_0830_0900shape.tar.gz", 
    "ftp://ftp.aoml.noaa.gov/hrd/pub/hwind/PostAnalysis/2005/AL122005/0830/1200/AL122005_0830_1200shape.tar.gz")

You'll notice that each of the above URLs is a link to a zipped (“tarred”) file. Rather than laboriously unzipping them and reading each one in manually, I decided to let R do the heavy-lifting. Below, I pre-create a list in which each shapefile (38 total) will come to reside.

Then, I use a for-loop to download, unzip, and read in the corresponding spatial data from a temporary directory. I then blow away the temporary directory at the end of each loop reiteration and recreate it. On my Macbook Pro, this part took about 2.5 minutes.

shapes = list()
tmpdir = tempdir()
for (i in 1:length(urls)) {
    setwd(tmpdir)
    file = basename(urls)[i]
    download.file(urls[i], paste(tmpdir, "/", file, sep = ""), quiet = T)
    untar(file, exdir = tmpdir)
    shapes[i] = readOGR(dsn = tmpdir, layer = substr(basename(dir(tmpdir)[1]), 
        1, nchar(basename(dir(tmpdir)[1])) - 4), verbose = F)
    unlink(tmpdir, recursive = T)
    dir.create(tmpdir)
}

“shapes”“ is a now a list stuffed with 38 SpatialPointsDataFrames, one for each available H*Wind analysis for Hurricane Katrina. The SPDF's range temporally from 25 August (21z) to 30 August (12z).

Next, we create another list called plots.list. This list will go on to contain an individual plot. I also use the lubridate package to generate datetime stamps for use in the animation.

plots.list = list()
date = ymd_h("2005-08-25-21")
## 1 parsed with %Y-%m-%d-%H
dates = date + c(0:length(urls)) * hours(3)
for (i in 1:length(urls)) {
    box = bbox(shapes[[i]])
    cl = map("worldHires", xlim = c(box[1], box[3]), ylim = c(box[2] * 0.6, 
        box[4]), plot = FALSE)
    clp1 = map2SpatialLines(cl)  #, proj4string=CRS(ll))
    plots.list[[i]] = spplot(shapes[[i]], "SFC_SPD", key.space = "right", cuts = c(0, 
        18, 33, 43, 50, 58, 70, 100), col.regions = c("white", "darkslategray1", 
        rev(heat_hcl(5))), sub = paste(dates[i]), main = expression(paste("Hurricane Katrina Winds [m", 
        s^-1, "]")), panel = function(x, y, ...) {
        panel.pointsplot(x, y, ...)
        sp.lines(clp1, col = "black", lwd = 0.5)
    })
}

Here is a simple plot of Hurricane Katrina near her peak intensity. The winds (ms\( ^-1 \)) are categorized as sub-tropical storm strength, tropical storm strength, and category 1-5 hurricane strength on the Saffir-Simpson scale.

print(plots.list[[22]])

plot of chunk plotK

Finally, we can turn these successive plots into an HTML animation (this will take another few minutes to run). This will create its own HTML file, but is not shown here.

ani.options(interval = 0.2, ani.height = 700)
saveHTML({
    for (i in 1:length(urls)) print(plots.list[[i]])
}, movie.name = "Katrina_HWinds")
## HTML file created at:
## /var/folders/k7/1dd8g1j14m1_xktjz8923c4m0000gn/T//Rtmpfil0W7/index.html
## You may use ani.options(outdir = getwd()) or saveHTML(..., outdir =
## getwd()) to generate files under the current working directory.