R/read.storms.R

Defines functions read.hurdat2 read.imilast

Documented in read.hurdat2 read.imilast

#' Read cyclone data
#' 
#' Methods for reading cyclone data.
#'
#' \code{read.imilast} reads data from files following the standards of the IMILAST project
#' (Neu et al., 2013, IMILAST: A Community Effort to Intercompare Extratropical Cyclone Detection
#' and Tracking Algorithms. Bull. Amer. Meteor. Soc., 94, 529-547,
#' \url{https://doi.org/10.1175/BAMS-D-11-00154.1}).
#'
#' \code{read.hurdat2} reads data from the Atlantic hurricane database
#' (\url{http://www.nhc.noaa.gov/data/#hurdat})
#'
#' @name read.imilast
#' @aliases read.hurdat2
#'
#' @param fname filename (for \code{read.hurdat}, filename can also be a url)
#' @param path path to file
#' @param verbose a boolean; If FALSE, do not display comments (silent mode).
#' If TRUE, display extra information on progress.
#'
#' @return An "events" "data.frame" object containing the date, time, lon, and
#' lat, as well as additional information (e.g., trajectory number, slp or
#' other measure of storm strength) of the cyclones.
#'
#' @author K. Parding
#'
#' @keywords cyclones storms IMILAST hurdat2
#'
#' @export
read.imilast <- function(fname,path=NULL,verbose=FALSE) {
  if(verbose) print('read.imilast')
  if(!is.null(path)) fname <- file.path(path,fname)
  # read and rearrange file header
  if(verbose) print(paste('reading file header:'))
  h <- tolower(readLines(fname,1))
  if(verbose) print(h)
  if(verbose) print('rearranging')
  h <- unlist(strsplit(h,','))
  if(length(h)==1) h <- unlist(strsplit(h,' '))
  h <- gsub('^\\s+|\\s+$','',h)
  h[grepl('cyclone',h) | grepl('trackn',h)] <- 'trajectory'
  h[grepl('lati',h) | grepl('latn',h)] <- 'lat'
  h[grep('long',h)] <- 'lon'
  h[grepl('99',h) | grepl('code',h)] <- 'code99'
  h[grepl('date',h) | grepl('yyyymmddhh',h)] <- 'datetime'
  h[grep('yyyy',h)] <- 'year'
  h[grep('mm',h)] <- 'month'
  h[grep('dd',h)] <- 'day'
  h[grepl('hh',h) | grepl('timestep\\.',h) | grepl('timestep\\_',h)] <- 'time'
  h[grepl('step',h) | grepl('ptn',h)] <- 'timestep'
  h <- unique(h)
  if(verbose) print(paste(h,collapse=', '))
  # check width of columns
  l <- readLines(fname,4)[4]
  l <- gsub('^\\s+|\\s+$','',l)
  blanks <- unlist(gregexpr(' ',l))
  breaks <- blanks[!(blanks %in% as.integer(blanks+1))]
  w <- c(blanks[1]-1,
         breaks[2:length(breaks)]-breaks[1:(length(breaks)-1)],
         nchar(l)-breaks[length(breaks)]+1)
  if(verbose) print(paste('width of columns:',paste(w,collapse=',')))                
  # read data
  if(verbose) print('reading data')
  x <- read.fwf(fname,widths=w,col.names=h,skip=1)
  x <- x[x$code99<90,]
  x <- x[!is.na(x$lon),]
  # rearrange date and time information
  dates <- round(x['datetime'][[1]]*1E-2)
  times <- x['datetime'][[1]] - round(dates)*1E2
  x['date'] <- dates
  x['time'] <- times
  x <- x[,-which(names(x) %in% c('datetime','year','month','day','timestep'))]
  #add attributes
  param <- 'storm tracks'
  longname <- 'mid-latitude storm trajectories'
  src <- 'IMILAST'
  url <- 'http://journals.ametsoc.org/doi/abs/10.1175/BAMS-D-11-00154.1'
  ref <- paste('Neu et al. 2013: IMILAST: A Community Effor to Intercompare Extratroptical Cyclone Detection and Tracking Algorithms.',
               'Bull. Amer. Meteor. Soc., 94, 529-547.')
  if (x$code99[1]>9) {
    method <- paste('M',as.character(x$code99[1]),sep='')
  } else {
    method <- paste('M0',as.character(x$code99[1]),sep='')
  }
  x <- as.events(x,longname=longname,param=param,method=method,src=src,
                 reference=ref,file=file.path(path,fname),url=url,verbose=verbose)
  attr(x, 'history')= history.stamp() 
  invisible(x)
}

#fname <- 'http://www.aoml.noaa.gov/hrd/hurdat/Data_Storm.html'
#' @export
read.hurdat2 <- function(fname='http://www.nhc.noaa.gov/data/hurdat/hurdat2-1851-2016-041117.txt',
                         path=NULL,verbose=FALSE,...) {
  if(verbose) print('read.hurdat2')
  if(verbose) print(paste('file:',fname))
  if(!is.null(path) & !is.url(fname)) {
    fname <- file.path(path,fname)
  } else if (is.url(fname)) {
    destfile <- sub('http://','',fname)
    destfile <- sub('.html','.txt',destfile)
    destfile <- sub('.*/','',destfile)
    if (!is.null(path)) destfile <- file.path(path,destfile)
    if(!file.exists(destfile)) download.file(url=fname, destfile, method='auto', 
                                             quiet=FALSE, mode='w', cacheOK=TRUE)
    fname <- destfile
  }
  hurdat2 <- readLines(fname)
  n <- as.vector(sapply(hurdat2,nchar))
  i.storm <- which(n>80)
  i.name <- which(diff(n)>50)
  i.start <- min(i.name)
  x <- strsplit(hurdat2[i.storm],',')
  x <- do.call(rbind, x)
  x <- x[,-21]
  d <- dim(x)
  ri <- sapply(x[,3],function(x) gsub(' ','',x))
  ri[nchar(ri)==0] <- 0
  ri <- sapply(ri,function(x) switch(x,'0'=0,'L'=1,'W'=2,'P'=3,'I'=4,'C'=5,'S'=6,'G'=7,'T'=8))
  ri <- as.numeric(unlist(as.character(ri)))
  dict.ri <- seq(0,8)
  names(dict.ri) <- c('-','L','W','P','I','C','S','G','T')
  hu <- unlist(sapply(x[,4],function(x) gsub(' ','',x)))
  hu <- sapply(hu,function(x) switch(x,'TD'=1,'TS'=2,'HU'=3,'EX'=4,'SD'=5,'SS'=6,'LO'=7,'WV'=8,'DB'=9))
  hu <- as.numeric(unlist(as.character(hu)))
  dict.hu <- seq(1,9)
  names(dict.hu) <- c('TD','TS','HU','EX','SD','SS','LO','WV','DB')
  x[,3] <- ri
  x[,4] <- hu
  x[,5] <- sapply(x[,5],function(x) {
    y <- as.numeric(gsub('N|S','',x))
    if(grepl('S',x)) y <- -y
    return(y) })
  x[,6] <- sapply(x[,6],function(x) {
    y <- as.numeric(gsub('E|W','',x))
    if(grepl('W',x)) y <- -y
    return(y) })
  x <- as.numeric(x)
  dim(x) <- d
  h <- strsplit(hurdat2[i.name],',')
  h <- do.call(rbind, h)
  h <- apply(h,c(1,2),function(x) gsub(' ','',x))
  h[,1] <- sapply(h[,1],function(x) gsub('AL','',x))
  i.x <- sapply(i.storm, function(i) max(seq(length(i.name))[i.name<i]))
  x <- cbind(as.numeric(h[i.x,3]),x)
  x <- cbind(as.numeric(h[i.x,1]),x)
  colnames(x) <- c('trajectory','n','date','time','record.id','status',
                   'lat','lon','max.speed','pcent',
                   'r34.ne','r34.se','r34.sw','r34.nw',
                   'r50.ne','r50.se','r50.sw','r50.nw',
                   'r64.ne','r64.se','r64.sw','r64.nw')
  if(verbose) print(colnames(x))
  dict.names <- h[,2]
  names(dict.names) <- factor2numeric(h[,1])
  x <- as.events(x,longname='tropical storms and hurricanes',
                 param='storm tracks',method='HURDAT 2nd generation',
                 src='National Hurricane Center (NHC) revised Atlantic hurricane database (HURDAT2)',
                 reference='Landsea, C. W., et al. 2004: The Atlantic hurricane database re-analysis project: Documentation for the 1851-1910 alterations and additions to the HURDAT database. Hurricanes and Typhoons: Past, Present and
Future, R. J. Murname and K.-B. Liu, Eds., Columbia University Press, 177-221.',
                 file=fname,url=fname,verbose=verbose)
  attr(x,'name') <- dict.names
  attr(x,'record.id') <- dict.ri
  attr(x,'status') <- dict.names
  invisible(x)
}
metno/esd documentation built on March 9, 2024, 11:21 a.m.