#' Fire Season Start and End
#'
#' @description \code{\link{fire_season}} calculates the start and end fire
#' season dates for a given weather station. The current method used in the
#' function is based on three consecutive daily maximum temperature thresholds
#' (Wotton and Flannigan 1993, Lawson and Armitage 2008). This function process
#' input from a single weather station.
#'
#' An important aspect to consider when calculating Fire Weather Index (FWI)
#' System variables is a definition of the fire season start and end dates
#' (Lawson and Armitage 2008). If a user starts calculations on a fire season
#' too late in the year, the FWI System variables may take too long to reach
#' equilibrium, thus throwing off the resulting indices. This function presents
#' two method of calculating these start and end dates, adapted from Wotton and
#' Flannigan (1993), and Lawson and Armitage (2008). The approach taken in this
#' function starts the fire season after three days of maximum temperature
#' greater than 12 degrees Celsius. The end of the fire season is determined
#' after three consecutive days of maximum temperature less than 5 degrees
#' Celsius. The two temperature thresholds can be adjusted as parameters in
#' the function call. In regions where temperature thresholds will not end a
#' fire season, it is possible for the fire season to span multiple years, in
#' this case setting the multi.year parameter to TRUE will allow these
#' calculations to proceed.
#'
#' This fire season length definition can also feed in to the overwinter DC
#' calculations (\link{overwinter_drought_code}). View the cffdrs package help
#' files for an example of using the \code{fire_season},
#' \link{overwinter_drought_code}, and \link{fwi} functions in conjunction.
#'
#' @param input A data.frame containing input variables of including the
#' date/time and daily maximum temperature. Variable names have to be the same
#' as in the following list, but they are case insensitive. The order in which
#' the input variables are entered is not important either.
#'
#' \tabular{lll}{
#' \var{yr} \tab (required) \tab Year of the observations\cr
#' \var{mon} \tab (required) \tab Month of the observations\cr
#' \var{day} \tab (required) \tab Day of the observations\cr
#' \var{tmax} \tab (required) \tab Maximum Daily Temperature (degrees C)\cr
#' \var{snow_depth}
#' \tab (optional) \tab Is consistent snow data in the input?\cr
#' }.
#'
#' @param fs.start Temperature threshold (degrees C) to start the fire season
#' (default=12)
#' @param fs.end Temperature threshold (degrees C) to end the fire season
#' (default=5)
#' @param method Method of fire season calculation. Options are "wf93"" or
#' "la08" (default=WF93)
#' @param consistent.snow Is consistent snow data in the input? (default=FALSE)
#' @param multi.year Should the fire season span multiple years?
#' (default=FALSE)
#' @return \link{fire_season} returns a data frame of season and start and end
#' dates. Columns in data frame are described below.
#'
#' Primary FBP output includes the following 8 variables:
#' \item{yr }{Year of the fire season start/end date}
#' \item{mon }{Month of the fire season start/end date}
#' \item{day }{Day of the fire season start/end date}
#' \item{fsdatetype }{
#' Fire season date type (values are either "start" or "end")}
#' \item{date}{Full date value}
#'
#' @author Alan Cantin, Xianli Wang, Mike Wotton, and Mike Flannigan
#'
#' @seealso \code{\link{fwi}, \link{overwinter_drought_code}}
#'
#' @references Wotton, B.M. and Flannigan, M.D. (1993). Length of the fire
#' season in a changing climate. Forestry Chronicle, 69, 187-192.
#'
#' \url{https://www.ualberta.ca/~flanniga/publications/1993_Wotton_Flannigan.pdf}
#'
#' Lawson, B.D. and O.B. Armitage. 2008. Weather guide for the Canadian Forest
#' Fire Danger Rating System. Nat. Resour. Can., Can. For. Serv., North. For.
#' Cent., Edmonton, AB \url{https://cfs.nrcan.gc.ca/pubwarehouse/pdfs/29152.pdf}
#' @keywords methods
#' @examples
#'
#' library(cffdrs)
#' # The standard test data:
#' data("test_wDC")
#' print(head(test_wDC))
#' ## Sort the data:
#' input <- with(test_wDC, test_wDC[order(id, yr, mon, day), ])
#'
#' # Using the default fire season start and end temperature
#' # thresholds:
#' a_fs <- fire_season(input[input$id == 1, ])
#'
#' # Check the result:
#' a_fs
#'
#' # yr mon day fsdatetype
#' # 1 1999 5 4 start
#' # 2 1999 5 12 end
#' # 3 1999 5 18 start
#' # 4 1999 5 25 end
#' # 5 1999 5 30 start
#' # 6 1999 10 6 end
#' # 7 2000 6 27 start
#' # 8 2000 10 7 end
#'
#' # In the resulting data frame, the fire season starts
#' # and ends multiple times in the first year. It is up to the user for how
#' # to interpret this.
#'
#' # modified fire season start and end temperature thresholds
#' a_fs <- fire_season(input[input$id == 1, ], fs.start = 10, fs.end = 3)
#' a_fs
#' # yr mon day fsdatetype
#' # 1 1999 5 2 start
#' # 2 1999 10 20 end
#' # 3 2000 6 16 start
#' # 4 2000 10 7 end
#' # select another id value, specify method explicitly
#' b_fs <- fire_season(input[input$id == 2, ], method = "WF93")
#' # print the calculated fire_season
#' b_fs
#' # yr mon day fsdatetype
#' # 1 1980 4 21 start
#' # 2 1980 9 19 end
#' # 3 1980 10 6 start
#' # 4 1980 10 16 end
#' # 5 1981 5 21 start
#' # 6 1981 10 13 end
#'
#' @export fire_season
fire_season <- function(
input,
fs.start = 12,
fs.end = 5,
method = "WF93",
consistent.snow = FALSE,
multi.year = FALSE) {
#############################################################################
# Description:
# Calculation of fire season. The intent of this function is to allow
# for calculation of the start and end dates of a fire season. Knowledge
# of the start and end dates allows for more accurate calculation of Fire
# Weather Indices. Only 1 method is presented here, however future
# modifications will allow the inclusion of other methods.
#
# The current method contained within are contained in the following
# article:
#
# Wotton B.M. and Flannigan, M.D. 1993. Length of the fire season in a
# changing climate. Forestry Chronicle, 69: 187-192.
# **Note that snow depth/cover is not currently included due to a lack of
# widespread snow coverage data, however this will be a future addition.
#
# Args:
# input: Single station weather data input stream - view fire_season.Rd
# documentation for full description.
# fs.start: Temperature threshold to start the fire season (deg celcius)
# fs.end: Temperature threshold to end the fire season (deg celcius)
# method: Fire Season calculation method. The default and only current
# method being used is "WF93".
# consistent.snow TRUE/FALSE value if consistent snow data is available
# if it is not, then we will default to WF93.
#
#
# Returns:
# seasonStartEnd: data.frame containing start and end dates of fire
# seasons for a particular weather station.
#
#############################################################################
names(input) <- tolower(names(input))
# Ensure that required variables exist, if not, stop and give message
# If variables exist, conver to local scope variables
if ("yr" %in% names(input)) {
yr <- input$yr
} else {
stop("Year was not provided, year is required for this function.")
}
if ("mon" %in% names(input)) {
mon <- input$mon
if (!all(mon %in% seq(1, 12))) {
stop("mon value is out of bounds (1-12), stopping execution.")
}
} else {
stop("Month was not provided, month is required for this function.")
}
if ("day" %in% names(input)) {
day <- input$day
if (!all(day %in% seq(1, 31))) {
stop("day value is out of bounds (1-31), stopping execution.")
}
} else {
stop(paste0(
"day was not provided, day is required for this function,",
" stopping execution.."
))
}
if ("tmax" %in% names(input)) {
tmax <- input$tmax
} else {
stop(paste0(
"Maximum Daily Temperature (tmax) was not provided, daily tmax is",
" required for this function."
))
}
method <- tolower(method)
if (method != "wf93" & method != "la08") {
stop(paste0(
"Selected method \"", method,
"\" is unavailable, read documentation for available methods."
))
}
# Get length of dataset
n0 <- length(tmax)
seasonActive <- FALSE
seasonStartEnd <- NULL
# Run Wotton & Flannign 1993 fire season calculation method (without snow)
if (method == "wf93") {
for (k in 1:n0) {
if (k > 3) {
# If we are not already in a fire season AND
# the last 3 days are all greater than the starting temperature
# threshold, then set start date.
if (!seasonActive & (all(tmax[seq(k - 3, k - 1, 1)] > fs.start))) {
seasonActive <- TRUE # set season to active
theday <- day[k]
# If the data is starting us on January 4th, then we should have
# started on January 1st Should be modified to work on any starting
# data, but for now, just calendar year to allow for year-round
# calculations.
if (!multi.year) {
if (mon[k] == 1 && day[k] == 4) {
theday <- day[k - 3]
}
}
# Bind the start date to the data.frame
seasonStartEnd <- rbind(
seasonStartEnd,
data.frame(
yr = yr[k],
mon = mon[k],
day = theday,
fsdatetype = "start"
)
)
}
# I we are already in a fire season AND
# the last 3 days are less than the end season temperature threshold
# thn set end date.
if (seasonActive & all(tmax[seq(k - 3, k - 1, 1)] < fs.end)) {
seasonActive <- FALSE
# Bind the end date to the data frame.
seasonStartEnd <- rbind(
seasonStartEnd,
data.frame(
yr = yr[k],
mon = mon[k],
day = day[k],
fsdatetype = "end"
)
)
}
}
}
# Run the CFS1984 / Lawson and Armitage 2008 combined procedure
} else {
if (method == "la08") {
# In regions normally covered by snow, begin calculations 3rd day after
# snow has left the area
if (consistent.snow) {
# Check that data has snow_depth variable
if (!("snow_depth" %in% names(input))) {
stop(paste0(
"Snow depth is required for the selected method \"", method,
"\", read documentation for appropriate use."
))
} else {
# set a local snow_depth variable
snow_depth <- input$snow_depth
for (k in 1:n0) {
# Must be more than 3 days in the dataset to test this out
if (k > 3) {
# If we are not already in a fire season AND
# the last 3 days (inclusive) are all snow free
# then set the starting date
if (!seasonActive & (all(snow_depth[seq(k - 2, k, 1)] <= 0))) {
seasonActive <- TRUE # set season to active
theday <- day[k]
# If running annual seasons only, and if the data is starting us
# on January 4th, then we should have started on January 1st
# Should be modified to work on any starting data, but for now,
# just calendar year to allow for year-round calculations.
if (!multi.year) {
if (mon[k] == 1 && day[k] == 4) {
theday <- day[k - 3]
}
}
# Bind the start date to the data.frame
seasonStartEnd <- rbind(
seasonStartEnd,
data.frame(
yr = yr[k],
mon = mon[k],
day = theday,
fsdatetype = "start"
)
)
}
# Stop the season if we are already in a fire season AND
# there is a day with snow on the ground OR it is after
# November 30, and temperatures dip below the fs.end
# threshold for LA08, which is 12C by default.
if (seasonActive &
(snow_depth[k] > 0 |
(mon[k] == 12 & all(tmax[seq(k - 2, k, 1)] < fs.end))
)
) {
seasonActive <- FALSE
# Bind the end date to the data frame.
seasonStartEnd <- rbind(
seasonStartEnd,
data.frame(
yr = yr[k],
mon = mon[k],
day = day[k],
fsdatetype = "end"
)
)
}
}
}
}
} else {
# Not an area of consistent snow, so run the wf93 algorithm
fire_season(input, fs.start, fs.end, method = "WF93")
}
}
}
# If there is a start and an end on the same date, remove both
# This may happen when starting/ending in Dec for LA08 method
seasonStartEnd$date <- as.Date(as.POSIXlt(
paste0(seasonStartEnd$yr, "-", seasonStartEnd$mon, "-", seasonStartEnd$day)
))
dups <- seasonStartEnd[duplicated(seasonStartEnd[, 0:3]), ]
seasonStartEnd <- seasonStartEnd[!seasonStartEnd$date %in% dups$date, ]
# Return the season start end dates data.frame to caller
return(seasonStartEnd)
}
fireSeason <- function(...) {
.Deprecated("fire_season")
return(fire_season(...))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.