#!/usr/bin/Rscript
#####################################
### Author: M. Forrest (matthew.forrest@senckenberg.de)
###
### Biome classifications to go from LPJ-GUESS output to different biome schemes
###############################################################################
########### SMITH ET AL. 2014 BIOME CLASSIFICATION ############################
###############################################################################
#' Rules to classify biomes as per Smith et al. 2014
#'
#' Based on LAI only, see paper for details. Note that the code here follows the actual script used at Lund, rather than the table in the paper
#' which doesn't quite give the whole picture.
#'
#' @param x Numerical vector of LAI values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-17, ordering as in Smith et al 2014 Figure)
#' @keywords internal
#' @include classes.R
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
Smith2014BiomeRules <- function(x){
# BIOME 1 - Tropical Rain Forest
if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & as.numeric(x[['LAI_std_TrBEFractionOfTree']]) > 0.6 & x[['LAI_std_MaxTree']] == "TrBE") {return("Tropical Rain Forest")}
# BIOME 2 - Tropical Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TrBRFractionOfTree']]) > 0.6) & (x[['LAI_std_MaxTree']] == "TrBR" | x[['LAI_std_MaxTree']] == "TrTBR")) {return("Tropical Deciduous Forest")}
# BIOME 3 - Tropical Seasonal Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & as.numeric(x[['LAI_std_TropicalFractionOfTree']] )> 0.5 & (x[['LAI_std_MaxTree']] == "TrBE" | x[['LAI_std_MaxTree']] == "TrBR" | x[['LAI_std_MaxTree']] == "TrTBR")) {return("Tropical Seasonal Forest")}
# BIOME 4 - Boreal Evergreen Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) > 0.8 & (x[['LAI_std_MaxTree']] == "BNE" | x[['LAI_std_MaxTree']] == "IBS" | x[['LAI_std_MaxTree']] == "BIBS")) {return("Boreal Evergreen Forest/Woodland")}
# BIOME 5 - Boreal Deciduous Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) > 0.8 & x[['LAI_std_MaxTree']] == "BNS") {return("Boreal Deciduous Forest/Woodland")}
# BIOME 6 - Temperate Broadleaved Evergreen Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TeBEFractionOfTree']]) > 0.5 | as.numeric(x[['LAI_std_TeBSFractionOfTree']]) > 0.5) & x[['LAI_std_MaxTree']] == "TeBE") {return("Temperate Broadleaved Evergreen Forest")}
# BIOME 7 - Temperate Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TeBEFractionOfTree']]) > 0.5 | as.numeric(x[['LAI_std_TeBSFractionOfTree']]) > 0.5) & x[['LAI_std_MaxTree']] == "TeBS") {return("Temperate Deciduous Forest")}
# BIOME 8 - Temperate/Boreal Mixed Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) < 0.8 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) > 0.2 & as.numeric(x[['LAI_std_TemperateFractionOfTree']]) < 0.8 & as.numeric(x[['LAI_std_TemperateFractionOfTree']]) > 0.2) {return("Temperate/Boreal Mixed Forest") }
# BIOME 9 - Temperate Mixed Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5) {return("Temperate Mixed Forest")}
# BIOME 10 - Xeric Woodland/Shrubland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_GrassFraction']]) < 0.2) {return("Xeric Woodland/Shrubland")}
# BIOME 11 - Moist Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_Total']]) > 2.5) {return("Moist Savanna")}
# BIOME 12 - Dry Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_Total']]) <= 2.5) {return("Dry Savanna")}
# BIOME 13 - Arctic/alpine Tundra
else if(as.numeric(x[['LAI_std_Tree']]) < 0.5 & as.numeric(x[['LAI_std_Total']]) > 0.2 & as.numeric(x[['Lat']]) >= 54 && as.numeric(x[['LAI_std_Tree']]) < 0.5 * as.numeric(x[['LAI_std_Grass']])) {return("Arctic/Alpine Tundra")}
# BIOME 14 - Tall Grassland
else if(as.numeric(x[['LAI_std_Grass']]) > 2.0) {return("Tall Grassland")}
# BIOME 16 (1) - Arid Shrubland/Steppe
else if(as.numeric(x[['LAI_std_Tree']]) > 0.2 & as.numeric(x[['LAI_std_Grass']]) < 1.0) {return("Arid Shrubland/Steppe")}
# BIOME 15 - Dry Grassland
else if(as.numeric(x[['LAI_std_Grass']]) > 0.2) {return("Dry Grassland")}
# BIOME 16 (2) - Arid Shrubland/Steppe
else if(as.numeric(x[['LAI_std_Total']]) > 0.2) {return("Arid Shrubland/Steppe")}
# BIOME 17 - Desert
else if(as.numeric(x[['LAI_std_Total']]) <= 0.2) {return("Desert")}
# REMAINDER
else {
print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), "). Returning desert as per the Lund reference script." ))
return("Desert")
}
}
#' Smith et al 2014
#'
#' \strong{Smith2014BiomeScheme} Classification of global output as per Smith et al. 2014. Designed to be compared to Haxeltine and Prentice (1996)
#' map of potential natural biomes.
#'
#' @rdname BiomeScheme-class
#' @export
Smith2014BiomeScheme <- new("Scheme",
new("Quantity",
id = "Smith2014",
name = "Smith et al. 2014 Biomes",
colours = grDevices::colorRampPalette(c("Tropical Rain Forest" = "seagreen",
"Tropical Deciduous Forest" = "orange3",
"Tropical Seasonal Forest" = "green3",
"Boreal Evergreen Forest/Woodland" = "turquoise4",
"Boreal Deciduous Forest/Woodland"= "cyan",
"Temperate Broadleaved Evergreen Forest" = "dodgerblue3",
"Temperate Deciduous Forest" = "chartreuse",
"Temperate/Boreal Mixed Forest" = "seagreen1",
"Temperate Mixed Forest" = "darkseagreen1",
"Xeric Woodland/Shrubland" = "deeppink3",
"Moist Savanna" = "olivedrab2",
"Dry Savanna" = "goldenrod2",
"Arctic/Alpine Tundra" = "mediumpurple1",
"Tall Grassland" = "gold",
"Dry Grassland" = "lightgoldenrod2",
"Arid Shrubland/Steppe"= "lightcyan",
"Desert" = "grey75")),
units = c("Tropical Rain Forest",
"Tropical Deciduous Forest",
"Tropical Seasonal Forest",
"Boreal Evergreen Forest/Woodland",
"Boreal Deciduous Forest/Woodland",
"Temperate Broadleaved Evergreen Forest",
"Temperate Deciduous Forest",
"Temperate/Boreal Mixed Forest",
"Temperate Mixed Forest",
"Xeric Woodland/Shrubland",
"Moist Savanna",
"Dry Savanna",
"Arctic/Alpine Tundra",
"Tall Grassland",
"Dry Grassland",
"Arid Shrubland/Steppe",
"Desert"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = Smith2014BiomeRules,
layers.needed = list(
### Combine shade tolerances
list(quantity = "LAI_std", operator = "+", layers = c("BNE", "BINE", "BIBS"), new.layer = "BNE"),
list(quantity = "LAI_std", operator = 0, layers = "BINE"),
list(quantity = "LAI_std", operator = 0, layers = "BIBS"),
list(quantity = "LAI_std", operator = "+", layers = c("TeBS", "TeIBS"), new.layer = "TeBS"),
list(quantity = "LAI_std", operator = 0, layers = "TeIBS"),
list(quantity = "LAI_std", operator = "+", layers = c("TrBE", "TrIBE"), new.layer = "TrBE"),
list(quantity = "LAI_std", operator = 0, layers = "TrIBE"),
### Make totals
# Tree
list(quantity = "LAI_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "LAI_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
# Boreal
list(quantity = "LAI_std", operator = "+", layers = ".Boreal", new.layer = "Boreal"),
# Temperate
list(quantity = "LAI_std", operator = "+", layers = ".Temperate", new.layer = "Temperate"),
# Tropical
list(quantity = "LAI_std", operator = "+", layers = ".Tropical", new.layer = "Tropical"),
# Total
list(quantity = "LAI_std", operator = "+", layers = ".PFT", new.layer = "Total"),
### Get max tree
list(quantity = "LAI_std", operator = "max.layer", layers = ".Tree", new.layer = "MaxTree"),
# Make fractions
# GrassFraction
list(quantity = "LAI_std", operator = "/", layers = c("Grass", "Total"), new.layer = "GrassFraction"),
# BorealFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Boreal", "Tree"), new.layer = "BorealFractionOfTree"),
# TemperateFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Temperate", "Tree"), new.layer = "TemperateFractionOfTree"),
# TropicalFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Tropical", "Tree"), new.layer = "TropicalFractionOfTree"),
# TrBEFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TrBE", "Tree"), new.layer = "TrBEFractionOfTree"),
# TrBRFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TrBR", "Tree"), new.layer = "TrBRFractionOfTree"),
# TeBEFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TeBE", "Tree"), new.layer = "TeBEFractionOfTree"),
# TeBSFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TeBS", "Tree"), new.layer = "TeBSFractionOfTree")
),
data.reference = "Haxeltine and Prentice 1996",
published.reference = "Smith et al. 2014")
###############################################################################
########### HICKLER ET AL. 2012 BIOME CLASSIFICATION ##########################
###############################################################################
#' Rules to classify biomes as per Hickler et al. 2012
#'
#' Based on LAI, GDD5 and lon/lat only, see paper for details.
#'
#' @param x Numerical vector of LAI values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-13, ordering as in Hickler et al 2012 figure)
#' @keywords internal
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
Hickler2012Rules <- function(x){
Mediterranean.Total <- as.numeric(x[['LAI_std_Mediterranean']]) + as.numeric(x[['LAI_std_Supra-mediterranean']])
###### DESERTS (if LAI < 0.2)
if(as.numeric(x[['LAI_std_Total']] < 0.2)){
# BIOME 1 - Arctic/alpine desert
if(as.numeric(x[['LAI_std_gdd5']]) < 1200 & (x[['LAI_std_MaxPFT']] == "BES" | x[['LAI_std_MaxPFT']] == "C3_gr" | x[['LAI_std_MaxPFT']] == "Barren")) {return(1)}
# BIOME 13 - Desert
else if (as.numeric(x[['LAI_std_gdd5']]) > 1200) {return(13)}
}
###### TEMPERATE BIOMES (temperate woody fraction > 80%)
if(as.numeric(x[['LAI_std_TemperateFractionOfWoody']]) > 0.8){
###### FORESTS (if tree LAI > 2.0)
if(as.numeric(x[['LAI_std_Tree']]) > 2.0){
# BIOME 6 - Temperate beech and mixed beech forest
if(x[['LAI_std_MaxTree']] == "Fag_syl") {return(6)}
# BIOME 7 - Temperate mixed broad-leaved forest
else {return(7)}
}
}
###### BOREAL BIOMES (boreal woody fraction > 80%)
if(as.numeric(x[['LAI_std_BorealFractionOfWoody']]) > 0.8){
# BIOME 4 - Boreal/alpine conifer forest
if(as.numeric(x[['LAI_std_Tree']]) > 2.0) {return(4)}
# BIOME 3 - Boreal/alpine mixed woodland
if(as.numeric(x[['LAI_std_Tree']]) > 0.5) {return(3)}
}
###### MEDITERRANEAN BIOMES (mediterranean woody fraction > 80%)
if(as.numeric(x[['LAI_std_MediterraneanFractionOfWoody']]) > 0.8){
# BIOME 9 - Mediterranean sclerophyllous forest/woodland
if(as.numeric(x[['LAI_std_Tree']]) > 1.5) {return(9)}
# BIOME 10 - Mediterranean sclerophyllous shrubland
if(Mediterranean.Total > 0.5 & Mediterranean.Total > (0.5 * as.numeric(x[['LAI_std_Woody']])) & (Mediterranean.Total > as.numeric(x[['LAI_std_Grass']]))) {return(10)}
}
###### TRANSITIONAL FOREST BIOMES
if(as.numeric(x[['LAI_std_Tree']]) > 2.0) {
# HEMIBOREAL CLASSIFICATION APPLIED WHERE LAT > 52, LON > 3
# BIOME 5 - Hemiboreal mixed forest - only defined for Lat > 52, Lon > 3 as in Hickler 2012
if(as.numeric(x[['LAI_std_Boreal']]) > Mediterranean.Total & as.numeric(x[["Lat"]]) > 52 & as.numeric(x[["Lon"]]) > 3) {return(5)}
# ALTERNATE CLASSIFICATION OUTSIDE LAT > 52, LON > 3
# If boreal fraction of woody > 0.5 classify as a boreal type
else if(as.numeric(x[['LAI_std_Boreal']]) > Mediterranean.Total & as.numeric(x[['LAI_std_Boreal']]) > as.numeric(x[['LAI_std_Temperate']])) {
# BIOME 4- Boreal/alpine conifer forest
return(4)
}
# If temperate fraction of woody >= 0.5 classify as a temperate type
else if(as.numeric(x[['LAI_std_Boreal']]) > Mediterranean.Total & as.numeric(x[['LAI_std_Boreal']]) <= as.numeric(x[['LAI_std_Temperate']])){
# BIOME 6 - Temperate beech and mixed beech forest
if(x[['LAI_std_MaxTree']] == "Fag_syl") {return(6)}
# BIOME 7 - Temperate mixed broad-leaved forest
else {return(7)}
}
# BIOME 8 - Themophillous mixed broad-leaved forest
else if(as.numeric(x[['LAI_std_Boreal']]) < Mediterranean.Total) {return(8)}
}
###### MISCELLENEOUS
# BIOME 11 - Steppe Woodland
if(as.numeric(x[['LAI_std_Woody']]) > 0.5 & as.numeric(x[['LAI_std_Grass']]) > 0.5 & as.numeric(x[['LAI_std_gdd5']]) > 1200) {return(11)}
# BIOME 2 - Arctic/Alpine Tundra
if(as.numeric(x[['LAI_std_Tree']]) <= 0.5 & as.numeric(x[['LAI_std_gdd5']]) < 1200 & (x[['LAI_std_MaxPFT']] == "BES" | x[['LAI_std_MaxPFT']] == "C3_gr")) {return(2)}
# BIOME 12 - Steppe
if(as.numeric(x[['LAI_std_Total']]) > 0.2 & as.numeric(x[['LAI_std_gdd5']]) > 1200) {return(12)}
###### REMAINDER
else {
print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), ")" ))
print(x)
return(as.numeric(NA))
}
}
#' Meta-data describing the Hickler et al. 2012 european biome scheme for LPJ-GUESS output.
#'
#' \strong{Hickler2012BiomeScheme} Classification of european output as per Hickler et al. 2012.
#'
#' @rdname BiomeScheme-class
#' @export
Hickler2012BiomeScheme <- new("Scheme",
new("Quantity",
id = "Hickler2012",
name = "Hickler2012",
colours = grDevices::colorRampPalette(c("Arctic/alpine desert" = "lightblue1",
"Arctic/alpine tundra" = "lightsteelblue",
"Boreal/alpine mixed woodland" = "deepskyblue",
"Boreal/alpine conifer forest"= "royalblue4",
"Hemiboreal mixed forest" = "grey40",
"Temperate beech and mixed beech forest" = "green4",
"Temperate mixed broad-leaved forest" = "chartreuse3",
"Thermophilous mixed broad-leaved forest" = "yellowgreen",
"Mediterranean sclerophyllous forest/woodland" = "orange2",
"Mediterranean sclerophyllous shrubland" = "hotpink4",
"Steppe woodland" = "yellow3",
"Steppe" = "lemonchiffon1",
"Desert" = "grey75")),
units = c("Arctic/alpine desert" ,
"Arctic/alpine tundra",
"Boreal/alpine mixed woodland",
"Boreal/alpine conifer forest",
"Hemiboreal mixed forest",
"Temperate beech and mixed beech forest",
"Temperate mixed broad-leaved forest",
"Thermophilous mixed broad-leaved forest",
"Mediterranean sclerophyllous forest/woodland",
"Mediterranean sclerophyllous shrubland",
"Steppe woodland",
"Steppe",
"Desert"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = Hickler2012Rules,
layers.needed = list(
# Tree
list(quantity = "LAI_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "LAI_std", operator = "+", layers =".Grass", new.layer = "Grass"),
# Woody
list(quantity = "LAI_std", operator = "+", layers = c(".Tree", ".Shrub"), new.layer = "Woody"),
# Mediterranean
list(quantity = "LAI_std", operator = "+", layers =c(".Mediterranean"), "new.layer = Mediterranean"),
# SupraMediterranean
list(quantity = "LAI_std", operator = "+", layers =c(".Supra-mediterranean"), new.layer = "Supra-mediterranean"),
# MaxTree
list(quantity = "LAI_std", operator = "max.layer", layers =".Tree", new.layer = "MaxTree"),
# MaxPFT
list(quantity = "LAI_std", operator = "max.layer","layers =.PFT", new.layer = "MaxPFT"),
# GrassFraction
list(quantity = "LAI_std", operator = "/", layers =c("Grass", "Total"), new.layer = "GrassFraction"),
# BorealFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Boreal", "Woody"), new.layer = "BorealFractionOfTree"),
# TemperateFractionOfTree
list(quantity = "LAI_std", operator = "/", layers =c("Temperate", "Tree"), new.layer = "TemperateFractionOfTree"),
# MediterraneanFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Mediterranean", "Tree"), new.layer = "MediterraneanFractionOfTree")),
# needGDD5 = TRUE, !!! Need to implement this as a layer.needed in the style above above
data.reference = "- (Bohn)",
published.reference = "Hickler et al. 2012")
###############################################################################
########### FORREST ET AL. 2015 MEGABIOME CLASSIFICATION ######################
###############################################################################
#' Rules to classify coarses "mega biomes" as per Forrest et al. 2015
#'
#' # This is described in Forrest et al. 2015 Climates of the Past. Basically it calculates the Smith et al. 2014 biomes,
#' but assigns them to broader categories as per Harrison and Prentice 2006
#'
#' @param x Numerical vector of LAI values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-8, ordering as in the Forrest et al. 2015 figure)
#' @keywords internal
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
Forrest2015MegaBiomeRules <- function(x){
# BIOME 1 - Tropical Rain Forest
if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & as.numeric(x[['LAI_std_TrBEFractionOfTree']]) > 0.6 & x[['LAI_std_MaxTree']] == "TrBE") {return("Tropical Forest")}
# BIOME 2 - Tropical Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TrBRFractionOfTree']]) > 0.6 | as.numeric(x[['LAI_std_TrBRFractionOfTree']])) & (x[['LAI_std_MaxTree']] == "TrBR" | x[['LAI_std_MaxTree']] == "TrTBR")) {return("Savanna and Dry Woodlands")}
# BIOME 3 - Tropical Seasonal Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & as.numeric(x[['LAI_std_TropicalFractionOfTree']] )> 0.5 & (x[['LAI_std_MaxTree']] == "TrBE" | x[['LAI_std_MaxTree']] == "TrBR" | x[['LAI_std_MaxTree']] == "TrTBR")) {return("Tropical Forest")}
# BIOME 4 - Boreal Evergreen Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) > 0.8 & (x[['LAI_std_MaxTree']] == "BNE" | x[['LAI_std_MaxTree']] == "IBS" | x[['LAI_std_MaxTree']] == "BIBS")) {return("Boreal Forest")}
# BIOME 5 - Boreal Deciduous Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_BorealFractionOfTree']]) > 0.8 & x[['LAI_std_MaxTree']] == "BNS") {return("Boreal Forest")}
# BIOME 6 - Temperate Broadleaved Evergreen Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TeBEFractionOfTree']]) > 0.5 | as.numeric(x[['LAI_std_TeBSFractionOfTree']]) > 0.5) & x[['LAI_std_MaxTree']] == "TeBE") {return("Temperate Evergreen Forest")}
# BIOME 7 - Temperate Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (as.numeric(x[['LAI_std_TeBEFractionOfTree']]) > 0.5 | as.numeric(x[['LAI_std_TeBSFractionOfTree']]) > 0.5) & x[['LAI_std_MaxTree']] == "TeBS") {return("Temperate Deciduous Forest")}
# BIOME 8 - Temperate/Boreal Mixed Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5) {return("Temperate Deciduous Forest") }
# BIOME 9 - Temperate Mixed Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5) {return("Temperate Deciduous Forest")}
# BIOME 10 - Xeric Woodland/Shrubland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_GrassFraction']]) < 0.2) {return("Savanna and Dry Woodlands")}
# BIOME 11 - Moist Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_Total']]) > 2.5) {return("Savanna and Dry Woodlands")}
# BIOME 12 - Dry Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Tree']]) < 2.5 & as.numeric(x[['LAI_std_Total']]) <= 2.5) {return("Grasslands and Dry Shrublands")}
# BIOME 13 - Arctic/alpine Tundra
else if(as.numeric(x[['LAI_std_Tree']]) < 0.5 & as.numeric(x[['LAI_std_Total']]) > 0.2 & as.numeric(x[['Lat']]) >= 54 && as.numeric(x[['LAI_std_Tree']]) < 0.5 * as.numeric(x[['LAI_std_Grass']])) {return("Tundra")}
# BIOME 14 - Tall Grassland
else if(as.numeric(x[['LAI_std_Grass']]) > 2.0) {return("Grasslands and Dry Shrublands")}
# BIOME 16 (1) - Arid Shrubland/Steppe
else if(as.numeric(x[['LAI_std_Tree']]) > 0.2 & as.numeric(x[['LAI_std_Grass']]) < 1.0) {return("Grasslands and Dry Shrublands")}
# BIOME 15 - Dry Grassland
else if(as.numeric(x[['LAI_std_Grass']]) > 0.2) {return("Grasslands and Dry Shrublands")}
# BIOME 16 (2) - Arid Shrubland/Steppe
else if(as.numeric(x[['LAI_std_Total']]) > 0.2) {return("Grasslands and Dry Shrublands")}
# BIOME 17 - Desert
else if(as.numeric(x[['LAI_std_Total']]) < 0.2) {return("Desert")}
# REMAINDER
else {
print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), "). Returning desert as per the Lund reference script." ))
return("Desert")
}
}
#' Meta-data describing the Forrest et al. 2015 "mega biome" scheme for LPJ-GUESS output.
#'
#' \strong{Forrest2015BiomeScheme} Classification of global output into coarser mega biomes as per Forrest et al. 2015 (see appendix),
#' which is really just an aggregation of biomes following Harrison and Prentice 2006. Can be compared to aggregated Haxeltine and Prentice (1996) map.
#'
#' @rdname BiomeScheme-class
#' @export
#'
Forrest2015BiomeScheme <- new("Scheme",
new("Quantity",
id = "Forrest2015",
name = "Forrest et al. 2015",
colours = grDevices::colorRampPalette(c("Tropical Forest" = "seagreen",
"Temperate Evergreen Forest"= "dodgerblue3",
"Temperate Deciduous Forest "= "green3",
"Boreal Forest" = "turquoise4",
"Savanna and Dry Woodlands" = "olivedrab2",
"Grasslands and Dry Shrublands" = "goldenrod2",
"Tundra" = "mediumpurple1",
"Desert" = "grey75")),
units = c("Tropical Forest",
"Temperate Evergreen Forest",
"Temperate Deciduous Forest",
"Boreal Forest",
"Savanna and Dry Woodlands",
"Grasslands and Dry Shrublands",
"Tundra",
"Desert"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = Forrest2015MegaBiomeRules,
layers.needed = list(
### Combine shade tolerances
list(quantity = "LAI_std", operator = "+", layers = c("BNE", "BINE", "BIBS"), new.layer = "BNE"),
list(quantity = "LAI_std", operator = 0, layers = "BINE"),
list(quantity = "LAI_std", operator = 0, layers = "BIBS"),
list(quantity = "LAI_std", operator = "+", layers = c("TeBS", "TeIBS"), new.layer = "TeBS"),
list(quantity = "LAI_std", operator = 0, layers = "TeIBS"),
list(quantity = "LAI_std", operator = "+", layers = c("TrBE", "TrIBE"), new.layer = "TrBE"),
list(quantity = "LAI_std", operator = 0, layers = "TrIBE"),
### Make totals
# Tree
list(quantity = "LAI_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "LAI_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
# Boreal
list(quantity = "LAI_std", operator = "+", layers = ".Boreal", new.layer = "Boreal"),
# Temperate
list(quantity = "LAI_std", operator = "+", layers = ".Temperate", new.layer = "Temperate"),
# Tropical
list(quantity = "LAI_std", operator = "+", layers = ".Tropical", new.layer = "Tropical"),
# Total
list(quantity = "LAI_std", operator = "+", layers = ".PFT", new.layer = "Total"),
### Max tree
list(quantity = "LAI_std", operator = "max.layer", layers = ".Tree", new.layer = "MaxTree"),
# Make fractions
# GrassFraction
list(quantity = "LAI_std", operator = "/", layers = c("Grass", "Total"), new.layer = "GrassFraction"),
# BorealFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Boreal", "Tree"), new.layer = "BorealFractionOfTree"),
# TemperateFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Temperate", "Tree"), new.layer = "TemperateFractionOfTree"),
# TropicalFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("Tropical", "Tree"), new.layer = "TropicalFractionOfTree"),
# TrBEFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TrBE", "Tree"), new.layer = "TrBEFractionOfTree"),
# TrBRFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TrBR", "Tree"), new.layer = "TrBRFractionOfTree"),
# TeBEFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TeBE", "Tree"), new.layer = "TeBEFractionOfTree"),
# TeBSFractionOfTree
list(quantity = "LAI_std", operator = "/", layers = c("TeBS", "Tree"), new.layer = "TeBSFractionOfTree")
),
data.reference = "Haxeltine and Prentice 1996",
published.reference = "Forrest et al 2015, Smith et al. 2014")
#####################################################################
########### MEDITERRANEAN BIOME CLASSIFICATION ######################
#####################################################################
#' Rules to classify coarses Mediterranean biomes
#'
#' No reference yet
#'
#' @param x Numerical vector of LAI values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-8, ordering as in the Forrest et al. 2015 figure)
#' @keywords internal
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
MeditBiomeRules <- function(x){
# BIOME 1 - Grass Steppe
#else if(as.numeric(x[['LAI_std_Grass']]) > 1.0 & as.numeric(x[['LAI_std_Woody']] < 1.0)) {return(7)}
if(as.numeric(x[['LAI_std_Grass']]) > as.numeric(x[['LAI_std_Woody']])) {return("Grass Steppe or Montane Grassland")}
# BIOME 4 - Deciduous forest
#if(as.numeric(x[['LAI_std_Woody']]) > 2.5 && as.numeric(x[['LAI_std_SummergreenFractionOfTree']]) > 0.5) {return(4)} # 2
else if(as.numeric(x[['LAI_std_Woody']]) > 2.0 && (x[['LAI_std_MaxWoody']] == "TeBS")) {return("Deciduous Forest")} # 2
# BIOME 5 - Cold Montane forest
else if(as.numeric(x[['LAI_std_Woody']]) > 1.5 && (x[['LAI_std_MaxWoody']] == "BIBS" || x[['LAI_std_MaxWoody']] == "BNE")) {return("Cold Montane Forest")} # 1.5
# BIOME 2 - Needle-leaved evergreen forest
else if(as.numeric(x[['LAI_std_Woody']]) > 1.0 && x[['LAI_std_MaxWoody']] == "TeNE") {return("Needle-leaved Woodlands/Forest")} # 1.5
# BIOME 6 - Pre-steppe deciduous woodlands
#else if(as.numeric(x[['LAI_std_Woody']]) > 1.0 && as.numeric(x[['LAI_std_Grass']]) > as.numeric(x[['LAI_std_Woody']]) * 0.2 && (x[['LAI_std_MaxWoody']] == "TeBS" || x[['LAI_std_MaxWoody']] == "TeNE")) {return(6)}
else if(as.numeric(x[['LAI_std_Woody']]) > 1.0 && as.numeric(x[['LAI_std_Grass']]) > as.numeric(x[['LAI_std_Woody']]) * 0.2 && x[['LAI_std_MaxWoody']] == "TeBS") {return("Deciduous Steppe-Woodlands")}
# BIOME 6 - Pre-steppe deciduous woodlands
#else if(as.numeric(x[['LAI_std_Woody']]) > 1.0 && as.numeric(x[['LAI_std_Grass']]) > as.numeric(x[['LAI_std_Woody']]) * 0.2 && (x[['LAI_std_MaxWoody']] == "TeBS" || x[['LAI_std_MaxWoody']] == "TeNE")) {return(6)}
else if(as.numeric(x[['LAI_std_Woody']]) > 1.0 && as.numeric(x[['LAI_std_Grass']]) > as.numeric(x[['LAI_std_Woody']]) * 0.2 && x[['LAI_std_MaxWoody']] == "TeBE") {return("Evergreen Steppe-Woodlands")}
# BIOME 3 - Mediterranean woodland/scrub
else if(as.numeric(x[['LAI_std_Woody']]) > 1 && (x[['LAI_std_MaxWoody']] == "TeBE" || x[['LAI_std_MaxWoody']] == "MeES" || x[['LAI_std_MaxWoody']] == "MeRS")) {return("Mediterranean Sclerophyllous Woodlands/Forest")} # 1.5
# BIOME 7 - Remainder, Unclassified
else {
#print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), ")" ))
#print(x)
return("Unclassifiable/Other")
}
}
#' Meta-data describing a Mediterranean scheme for LPJ-GUESS output.
#'
#' \strong{MeditBiomeScheme} A biome classification scheme used for Turkey.
#'
#' @rdname BiomeScheme-class
#' @export
#'
MeditBiomeScheme <- new("Scheme",
new("Quantity",
id = "MeditBiomeScheme",
name = "Mediterranean Biomes",
colours = grDevices::colorRampPalette(c("Cold Montane Forest" = "royalblue4",
"Deciduous Forest" = "darkgreen",
"Deciduous Steppe-Woodlands" = "forestgreen",
"Grass Steppe or Montane Grassland" = "lightgreen",
"Mediterranean Sclerophyllous Woodlands/Forest" = "red4",
"Needle-leaved Woodlands/Forest" = "goldenrod4",
"Unclassifiable/Other" = "grey75",
"Evergreen Steppe-Woodlands" = "black")),
# units = c("Grass Steppe or Montane Grassland",
# "Needle-leaved Woodlands/Forest",
# "Mediterranean Sclerophyllous Woodlands/Forest",
# "Deciduous Forest",
# "Cold Montane Forest",
# "Deciduous Steppe-Woodlands",
# "Evergreen Steppe-Woodlands",
# "Unclassifiable/Other"),
units = c("Cold Montane Forest",
"Deciduous Forest",
"Deciduous Steppe-Woodlands",
"Grass Steppe or Montane Grassland",
"Mediterranean Sclerophyllous Woodlands/Forest",
"Needle-leaved Woodlands/Forest",
"Unclassifiable/Other",
"Evergreen Steppe-Woodlands"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = MeditBiomeRules,
layers.needed = list(
### Combine Shade Tolerances
list(quantity = "LAI_std", operator = "+", layers = c("BNE", "BINE", "BIBS"), new.layer = "BNE"),
list(quantity = "LAI_std", operator = 0, layers = "BINE"),
list(quantity = "LAI_std", operator = 0, layers = "BIBS"),
list(quantity = "LAI_std", operator = "+", layers = c("TeBS", "TeIBS", "IBS"), new.layer = "TeBS"),
list(quantity = "LAI_std", operator = 0, layers = "TeIBS"),
list(quantity = "LAI_std", operator = 0, layers = "IBS"),
### Calculate Totals
# Tree
list(quantity = "LAI_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "LAI_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
# Woody
list(quantity = "LAI_std", operator = "+", layers = c(".Tree", ".Shrub"), new.layer = "Woody"),
### Max woody
list(quantity = "LAI_std", operator = "max.layer", layers = c(".Tree", ".Shrub"), new.layer = "MaxWoody")
),
data.reference = "-",
published.reference = "-")
#################################################################################################################################
########### UNPUBLISHED BUT POSSIBLY USEFUL GLOBAL SCHEME BASED ON FEWER TYPES THAN SMITH ET AL. 2014 ##########################
#################################################################################################################################
#' Rules to classify coarser "mega biomes" from LAI, latitude and GDD5
#'
#' Unpublished but possibly useful in principle. Simpler classes that Smith et al 2014,
#' but more complex that Forrest et al 2015.
#'
#' @param x Numerical vector of LAI values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @keywords internal
#' @return Biomes code (1-13)
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
MegaBiomeRules_dev <- function(x){
# BIOME 1 - Tropical Rain Forest
if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & x[['LAI_std_MaxTree']] == "TrBE") {return(1)}
# BIOME 2 - Tropical Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & x[['LAI_std_MaxTree']] == "TrBR") {return(2)}
# BIOME 3 - Boreal Evergreen Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & (x[['LAI_std_MaxTree']] == "BNE" | x[['LAI_std_MaxTree']] == "IBS" | x[['LAI_std_MaxTree']] == "BIBS")) {return(3)}
# BIOME 4 - Boreal Deciduous Forest/Woodland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & x[['LAI_std_MaxTree']] == "BNS") {return(4)}
# BIOME 5 - Temperate Broadleaved Evergreen Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & (x[['LAI_std_MaxTree']] == "TeBE" | x[['LAI_std_MaxTree']] == "TeNE")) {return(5)}
# BIOME 6 - Temperate Deciduous Forest
else if(as.numeric(x[['LAI_std_Tree']]) > 2.5 & x[['LAI_std_MaxTree']] == "TeBS") {return(6)}
# BIOME 10 - Arctic/alpine Tundra
else if(as.numeric(x[['LAI_std_Tree']]) < 0.1 & as.numeric(x[['LAI_std_Total']]) > 0.5 & (as.numeric(x[['LAI_std_Lat']]) >= 54 | as.numeric(x[['LAI_std_GDD5']]) < 400)) {return(10)}
# BIOME 7 - Xeric Woodland/Shrubland
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_GrassFraction']]) < 0.2) {return(7)}
# BIOME 8 - Moist Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Total']]) > 2.5) {return(8)}
#else if(as.numeric(x[['LAI_std_Tree']]) > 0.5) {return(9)}
# BIOME 9 - Dry Savanna
else if(as.numeric(x[['LAI_std_Tree']]) > 0.5 & as.numeric(x[['LAI_std_Total']]) <= 2.5) {return(9)}
# BIOME 11 - Tall Grassland
else if(as.numeric(x[['LAI_std_Grass']]) > 2.0) {return(11)}
# BIOME 12 - Arid Shrubland/Grassland
else if(as.numeric(x[['LAI_std_Total']]) > 0.2) {return(12)}
# BIOME 13 - Desert
else if(as.numeric(x[['LAI_std_Total']]) < 0.2) {return(13)}
# REMAINDER
else {
print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), ")" ))
return(NA)
}
}
#' Meta-data describing an unpublished "mega biome" scheme for LPJ-GUESS output.
#'
#' \strong{DevMegaBiomeScheme} Unpublished for potentially useful classification of global biomes which is slightly simpler than Smith et al. 2014.
#'
#' @rdname BiomeScheme-class
#' @export
#'
DevMegaBiomeScheme <- new("Scheme",
new("Quantity",
id = "Megabiomes",
name = "Megabiomes",
colours = grDevices::colorRampPalette(c("Tropical Rain Forest" = "seagreen",
"Tropical Deciduous Forest" = "orange3",
"Boreal Evergreen Forest/Woodland" = "turquoise4",
"Boreal Deciduous Forest/Woodland"= "cyan",
"Temperate Evergreen Forest" = "dodgerblue3",
"Temperate Deciduous Forest" = "green3",
"Xeric Woodland/Shrubland" = "deeppink3",
"Moist Savanna" = "olivedrab2",
"Dry Savanna" = "goldenrod2",
"Arctic/Alpine Tundra" = "mediumpurple1",
"Tall Grassland" = "gold",
"Arid Shrubland/Grassland"= "lightcyan",
"Desert" = "grey75")),
units = c("Tropical Rain Forest",
"Tropical Deciduous Forest",
"Boreal Evergreen Forest/Woodland",
"Boreal Deciduous Forest/Woodland",
"Temperate Evergreen Forest",
"Temperate Deciduous Forest",
"Xeric Woodland/Shrubland",
"Moist Savanna",
"Dry Savanna",
"Arctic/Alpine Tundra",
"Tall Grassland",
"Arid Shrubland/Grassland",
"Desert"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = MegaBiomeRules_dev,
# needGDD5 = TRUE, !!! Need to implement this as a layer.needed in the style above above
layers.needed = list(
# Max Tree
list(quantity = "LAI_std", operator = "max.layer", layers = c(".Tree"), new.layer = "MaxTree")
),
data.reference = "Haxeltine and Prentice 1996",
published.reference = "-")
#################################################################################################################################
########### FIREMIP BIOMES ##########################
#################################################################################################################################
#' Rules to classify FireMIP biomes from fractionalcover of PFTs
#'
#' Unpublished but possibly useful in principle. Simpler classes that Smith et al 2014,
#' but more complex that Forrest et al 2015.
#'
#' @param x Numerical vector of FPC values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @keywords internal
#' @return Biomes code (1-10)
FireMIPBiomeRules <- function(x){
# BIOME 1 & 2 - croplands mosaics
if(as.numeric(x[['landCoverFrac_Crops']]) > 0.5) { return(1) }
if(as.numeric(x[['landCoverFrac_Crops']]) > 0.2) { return(2) }
# BIOMES 2-6 - Forests
#if(as.numeric(x[['landCoverFrac_Tree']]) > 0.6 & x[['landCoverFrac_Grass']] < 0.4) {
if(as.numeric(x[['landCoverFrac_Tree']]) > 0.6) {
# BIOME 2 Needleleaved forest
if(x[['landCoverFrac_MaxTree']] == "NE") { return(3) }
# BIOME 3 NS forest
else if(x[['landCoverFrac_MaxTree']] == "NS") { return(4) }
# BIOME 4 Summergreen forest
else if(x[['landCoverFrac_MaxTree']] == "BS") { return(5) }
# BIOME 5 Evergreen forest
else if(x[['landCoverFrac_MaxTree']] == "BE") { return(6) }
# BIOME 6 Raingreen forest
else if(x[['landCoverFrac_MaxTree']] == "BR") { return(7) }
}
# BIOME 3 Additional - Lower tree cover requirement for Needle-leaved Summergreen Forest
else if(as.numeric(x[['landCoverFrac_Tree']]) > 0.4 && x[['landCoverFrac_MaxTree']] == "NS") { return(4) }
# BIOMES 7 and 8 - Grassy systems
else if(as.numeric(x[['landCoverFrac_Grass']]) > 0.4 ) {
# BIOME 7 C4 grassy system
if(x[['landCoverFrac_MaxGrass']] == "landCoverFrac_C4G") { return(8) }
# BIOME 8 C3 grassy system
else if(x[['landCoverFrac_MaxGrass']] == "landCoverFrac_C3G") { return(9) }
}
# BIOMES 9 - Shrublands
else if(as.numeric(x[['landCoverFrac_Shrub']]) > 0.3 ) { return(10) }
# BIOME 10 - Sparse vegetation
else if(as.numeric(x[['landCoverFrac_Total']]) > 0.2 ) { return(11) }
# BIOME 11 Barren/Unclassified
else { return(12) }
}
#' Meta-data describing FireMIP biomes
#'
#' \strong{FireMIPBiomeScheme} Simple biomes based on a common PFT set for the FireMIP models
#'
#' @rdname BiomeScheme-class
#' @export
#'
FireMIPBiomeScheme <- new("Scheme",
new("Quantity",
id = "FireMIP",
name = "FireMIP Biomes",
colours = grDevices::colorRampPalette(c("Croplands Dominated \n(Croplands > 50%)" = "chartreuse",
"Croplands Mosaic \n(20% < Croplands < 50%)" = "darkseagreen1",
"Evergreen Needle-leafed Forest" = "darkblue",
"Summergreen Needle-leafed Forest" = "skyblue2",
"Broadleafed Summergreen Forest" = "darkgreen",
"Broadleafed Evergreen Forest" = "orchid4",
"Broadleafed Raingreen Forest" = "lightsalmon4",
"C4 Grassy System" = "orange",
"C3 Grassy System" = "lightgoldenrod",
"Shrubland" = "indianred3",
"Sparse/Other Vegetation" = "mistyrose2",
"Barren" = "gray75")),
units = c("Croplands Dominated \n(Croplands > 50%)",
"Croplands Mosaic \n(20% < Croplands < 50%)",
"Needle-leafed \nEvergreen Forest",
"Needle-leafed \nSummergreen Forest",
"Broadleafed \nSummergreen Forest",
"Broadleafed \nEvergreen Forest",
"Broadleafed \nRaingreen Forest",
"C4 Grassy \nSystem",
"C3 Grassy \nSystem",
"Shrubland",
"Sparse/Other \nVegetation",
"Barren"),
format = c("LPJ-GUESS-SPITFIRE-FireMIP",
"LPJ-GUESS-BLAZE-FireMIP",
"LPJ-GUESS-GlobFIRM-FireMIP",
"CLM-FireMIP",
"CTEM-FireMIP",
"JSBACH-FireMIP",
"Inferno-FireMIP",
"ORCHIDEE-FireMIP")),
rules = FireMIPBiomeRules,
layers.needed = list(
## Totals
# Tree
list(quantity = "landCoverFrac", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "landCoverFrac", operator = "+", layers = ".Grass", new.layer ="Grass"),
### Maxes
# Tree
list(quantity = "landCoverFrac", operator = "max.layer", layers = ".Tree", new.layer = "MaxTree"),
# Grass
list(quantity = "landCoverFrac", operator = "max.layer", layers = ".Grass", new.layer ="MaxGrass")
),
data.reference = "-",
published.reference = "-")
#################################################################################################################################
########### ##########################
#################################################################################################################################
#' Rules for biome scheme based on FPC
#'
#' lalala
#'
#' @param fpc Vector of FPC values
#' @keywords internal
FPCMegaBiomeRules <- function(x) {
# 9 - Desert
if (as.numeric(x[['fpc_Total']]) <= 0.2 &
as.numeric(x[['fpc_GDD5']]) >= 1200) {return(9)}
# 10 - Arctic desert
else if (as.numeric(x[['fpc_Total']]) <= 0.2 &
as.numeric(x[['fpc_GDD5']]) < 1200) {return(10)}
# 1 - Tropical Forest
else if (as.numeric(x[['fpc_Tree']]) > 0.6 &
as.numeric(x[['fpc_Tropical']]) > as.numeric(x[['fpc_Temperate']]) &
as.numeric(x[['fpc_Tropical']]) > as.numeric(x[['fpc_Boreal']])) {return(1)}
# 2 - Temperate Forest
else if (as.numeric(x[['fpc_Tree']]) > 0.6 &
as.numeric(x[['fpc_Temperate']]) > as.numeric(x[['fpc_Tropical']]) &
as.numeric(x[['fpc_Temperate']]) > as.numeric(x[['fpc_Boreal']])) {return(2)}
# 3 - Boreal Forest
else if (as.numeric(x[['fpc_Tree']]) > 0.2 &
as.numeric(x[['fpc_Boreal']]) > as.numeric(x[['fpc_Temperate']]) &
as.numeric(x[['fpc_Boreal']]) > as.numeric(x[['fpc_Tropical']])) {return(3)}
# 4 - Savannah
else if (as.numeric(x[['fpc_Tree']]) > 0.1 &
as.numeric(x[['fpc_Tree']]) <= 0.6 &
as.numeric(x[['fpc_C4G']]) >= as.numeric(x[['fpc_C3G']])) {return(4)}
# 5 - Temperate woodland
else if (as.numeric(x[['fpc_Tree']]) > 0.1 &
as.numeric(x[['fpc_Tree']]) <= 0.6 &
as.numeric(x[['fpc_C4G']]) < as.numeric(x[['fpc_C3G']]) &
as.numeric(x[['fpc_GDD5']]) > 1800) {return(5)}
# 6 - Tropical grassland
else if (as.numeric(x[['fpc_Tree']]) <= 0.1 &
as.numeric(x[['fpc_C4G']]) >= as.numeric(x[['fpc_C3G']])) {return(6)}
# 7 - Temperate grassland
else if (as.numeric(x[['fpc_Tree']]) <= 0.1 &
as.numeric(x[['fpc_C4G']]) < as.numeric(x[['fpc_C3G']]) &
as.numeric(x[['fpc_GDD5']]) > 1200) {return(7)}
# 8 - Tundra
else if (as.numeric(x[['fpc_Tree']]) <= 0.2) {return(8)}
# REMAINDER
else {
print(paste("Oops, not classified: Location (", as.numeric(x[['Lon']]), ",", as.numeric(x[['Lat']]), ")" ))
return(NA)
}
}
#' Meta-data for an FPC-based mega biome scheme
#'
#' \strong{FPCMegaBiome} an unpublished scheme based on fractional cover developed by Joerg Steinkamp
#'
#' @rdname BiomeScheme-class
#' @export
#'
FPCMegaBiomeScheme <- new("Scheme",
new("Quantity",
id = "FPCMegaBiomeScheme",
name = "FPCMegaBiomeScheme",
colours = grDevices::colorRampPalette(c("Tropical forest" = "darkgreen",
"Temperate forest" = "seagreen",
"Boreal forest" = "turquoise4",
"Savannah" = "tan",
"Woodland" = "tan2",
# "Taiga" = "tan4",
"C4-grassland" = "gold",
"C3-grassland" = "yellow",
"Tundra" = "seagreen2",
"Desert" = "lightgrey",
"Arctic desert" = "grey")),
units = c("Tropical forest",
"Temperate forest",
"Boreal forest",
"Savannah",
"Woodland",
# "Taiga",
"C4-grassland",
"C3-grassland",
"Tundra",
"Desert",
"Arctic desert"),
format = c("LPJ-GUESS", "LPJ-GUESS-SPITFIRE")),
rules = FPCMegaBiomeRules,
layers.needed = list(
# Tree
list(quantity = "fpc", operator = "+", layers = ".Tree", new.layer = "Tree"),
# Grass
list(quantity = "fpc", operator = "+", layers = ".Grass", new.layer = "Grass"),
# Boreal
list(quantity = "fpc", operator = "+", layers = ".Boreal", new.layer = "Boreal"),
# Temperate
list(quantity = "fpc", operator = "+", layers = ".Temperate", new.layer = "Temperate"),
# Tropical
list(quantity = "fpc", operator = "+", layers = ".Tropical", new.layer = "Tropical")
),
# needGDD5 = TRUE, !!! Need to implement this as a layer.needed in the style above above
data.reference = "-",
published.reference = "-")
#####################################################################
########### ADGVM(1) BIOME CLASSIFICATION SCHEMES #####################
#####################################################################
#####################################################################
########### SIMPLE BIOME CLASSIFICATION #############################
#####################################################################
#' Rules to classify tropical biomes from aDGVM1 output
#'
#' No reference yet
#'
#' @param x Numerical vector of vegetation over values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-5, baren, C4 grassland, C3 grassland, woodland, forest)
#' @keywords internal
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
#' @author Glenn Moncrief \email{glenn@@saeon.ac.za}
aDGVMBiomeRules <- function(x){
# BIOME 1 - Forest
if(as.numeric(x[['Cancov_Tree']]) >= 0.8) {return("Forest")}
# BIOME 2 - Woodland
else if(as.numeric(x[['Cancov_Tree']]) < 0.8 & x[['Cancov_Tree']] > 0.1 & x[['Cancov_ForTr_Fraction_Of_Tree']] > 0.5) {return("Woodland")}
# BIOME 3 - C4 Savanna
else if(as.numeric(x[['Cancov_Tree']]) < 0.8 & x[['Cancov_Tree']] > 0.1 & x[['Cancov_ForTr_Fraction_Of_Tree']] <= 0.5 & x[['C3C4_Ratio_Grass']] < 0.5) {return("C4 Savanna")}
# BIOME 4 - C3 Savanna
else if(as.numeric(x[['Cancov_Tree']]) < 0.8 & x[['Cancov_Tree']] > 0.1 & x[['Cancov_ForTr_Fraction_Of_Tree']] <= 0.5 & x[['C3C4_Ratio_Grass']] >= 0.5) {return("C3 Savanna")}
# BIOME 5 - C4 Grassland
else if(as.numeric(x[['Cancov_Tree']]) <= 0.1 & x[['LeafBiomass_Grass']] > 0.5 & x[['C3C4_Ratio_Grass']] >= 0.5) {return("C4 Grassland")}
# BIOME 6 - C3 Grassland
else if(as.numeric(x[['Cancov_Tree']]) <= 0.1 & x[['LeafBiomass_Grass']] > 0.5 & x[['C3C4_Ratio_Grass']] < 0.5) {return("C3 Grassland")}
# BIOME 7 - Desert
else if(as.numeric(x[['Cancov_Tree']]) <= 0.1 & x[['LeafBiomass_Grass']] <= 0.5) {return("Desert")}
# BIOME 8 - Remainder, Unclassified
else {
return("Unclassifiable/Other")
}
}
#' Meta-data describing a simple scheme for aDGVM2 output.
#'
#' \strong{SimpleAdgvm2BiomeScheme} SS document here
#'
#' @rdname BiomeScheme-class
#' @export
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
#' @author Glenn Moncrief \email{glenn@@saeon.ac.za}
aDGVMBiomeScheme <- new("Scheme",
new("Quantity",
id = "aDGVMBiomeScheme",
name = "aDGVM(1) Biomes",
colours = grDevices::colorRampPalette(c("Baren/Desert" = '#cccccc',
"C4 Grassland" = '#fad052',
"C3 Grassland" = '#f0f571',
"C4 Savanna" = '#a7c454',
"C3 Savanna" = '#caf062',
"Woodland" = '#5fde6e',
"Forest" = '#3c8f46',
"Unclassifiable/Other" = "grey75")),
units = c("Desert",
"C4 Grassland",
"C3 Grassland",
"C4 Savanna",
"C3 Savanna",
"Woodland",
"Forest",
"Unclassifiable/Other"),
format = c("aDGVM1")),
rules = aDGVMBiomeRules,
layers.needed = list( list(quantity = "LeafBiomass", operator = "+", layers = ".Grass", new.layer = "Grass"),
list(quantity = "Cancov", operator = "+", layers = ".Tree", new.layer = "Tree"),
list(quantity = "Cancov", operator = "/", layers = c("ForTr", "Tree"), new.layer = "ForTr_Fraction_Of_Tree"),
list(quantity = "C3C4_Ratio", operator = NULL, layers = "IgnoreThisWarningMessageHonestlyItsFine")),
data.reference = "-",
published.reference = "-")
#####################################################################
########### ADGVM2 BIOME CLASSIFICATION SCHEMES #####################
#####################################################################
#####################################################################
########### SIMPLE BIOME CLASSIFICATION #############################
#####################################################################
#' Rules to classify coarse tropical biomes
#'
#' No reference yet
#'
#' @param x Numerical vector of vegetation over values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-5, baren, C4 grassland, C3 grassland, woodland, forest)
#' @keywords internal
#' @author Simon Scheiter \email{Simon.Scheiter@@senckenberg.de}
SimpleAdgvm2BiomeRules <- function(x){
# BIOME 1 - Baren/Desert
if( as.numeric(x[['vegcover_std_Grass']])<=2 & as.numeric(x[['vegcover_std_Tree']])<=5) {return("Baren/Desert")}
# BIOME 2 - C4 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Tree']])<=5 & as.numeric(x[['vegcover_std_C3G']])<=as.numeric(x[['vegcover_std_C4G']])) {return("C4 Grassland")}
# BIOME 3 - C3 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Tree']])<=5 & as.numeric(x[['vegcover_std_C3G']])> as.numeric(x[['vegcover_std_C4G']])) {return("C3 Grassland")}
# BIOME 4 - Woodland
else if(as.numeric(x[['vegcover_std_Tree']])> 5 & as.numeric(x[['vegcover_std_Tree']])<=60) {return("Woodland")}
# BIOME 5 - Forest
else if(as.numeric(x[['vegcover_std_Tree']])> 60 ) {return("Forest")}
# BIOME 6 - Remainder, Unclassified
else {
return("Unclassifiable/Other")
}
}
#' Meta-data describing a simple scheme for aDGVM2 output.
#'
#' \strong{SimpleAdgvm2BiomeScheme} SS document here
#'
#' @rdname BiomeScheme-class
#' @export
#' @author Simon Scheiter \email{Simon.Scheiter@@senckenberg.de}
SimpleAdgvm2BiomeScheme <- new("Scheme",
new("Quantity",
id = "SimpleAdgvm2BiomeScheme",
name = "Simple aDGVM2 Biomes",
colours = grDevices::colorRampPalette(c("Baren/Desert" = '#cccccc',
"C4 Grassland" = '#fff700',
"C3 Grassland" = '#ffcf0f',
"Woodland" = '#94b6ff',
"Forest" = '#308a0a',
"Unclassifiable/Other" = "grey75")),
units = c("Baren/Desert",
"C4 Grassland",
"C3 Grassland",
"Woodland",
"Forest",
"Unclassifiable/Other"),
format = c("aDGVM")),
rules = SimpleAdgvm2BiomeRules,
layers.needed = list( list(quantity = "vegcover_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
list(quantity = "vegcover_std", operator = "+", layers = ".Tree", new.layer = "Tree")),
data.reference = "-",
published.reference = "-")
#####################################################################
########### SIMPLE BIOME CLASSIFICATION WITH HEIGHT #################
#####################################################################
#' Rules to classify coarse tropical biomes
#'
#' No reference yet
#'
#' @param x Numerical vector of vegetation over values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-5, baren, C4 grassland, C3 grassland, small forest, tall forest)
#' @keywords internal
#' @author Simon Scheiter \email{Simon.Scheiter@@senckenberg.de}
SimpleHeightAdgvm2BiomeRules <- function(x){
# BIOME 1 - Baren/Desert
if( as.numeric(x[['vegcover_std_Grass']])<=2 & as.numeric(x[['vegcover_std_Tree']])<=5) {return("Baren/Desert")}
# BIOME 2 - C4 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Tree']])<=5 & as.numeric(x[['vegcover_std_C3G']])<=as.numeric(x[['vegcover_std_C4G']])) {return("C4 Grassland")}
# BIOME 3 - C3 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Tree']])<=5 & as.numeric(x[['vegcover_std_C3G']])> as.numeric(x[['vegcover_std_C4G']])) {return("C3 Grassland")}
# BIOME 4 - Small forest
else if(as.numeric(x[['vegcover_std_Tree']])> 5 & as.numeric(x[['canopyheight_std_Tree']])<=5) {return("Small forest")}
# BIOME 5 - Tall forest
else if(as.numeric(x[['vegcover_std_Tree']])> 5 & as.numeric(x[['canopyheight_std_Tree']])> 5) {return("Tall forest")}
# BIOME 6 - Remainder, Unclassified
else {
return("Unclassifiable/Other")
}
}
#' Meta-data describing a simple scheme for aDGVM2 output.
#'
#' \strong{SimpleHeightAdgvm2BiomeScheme} SS document here
#' @rdname BiomeScheme-class
#' @export
#'
SimpleHeightAdgvm2BiomeScheme <- new("Scheme",
new("Quantity",
id = "SimpleHeightAdgvm2BiomeScheme",
name = "Simple aDGVM2 Biomes",
colours = grDevices::colorRampPalette(c("Baren/Desert" = '#cccccc',
"C4 Grassland" = '#fff700',
"C3 Grassland" = '#ffcf0f',
"Small forest" = '#94b6ff',
"Tall forest" = '#308a0a',
"Unclassifiable/Other" = "grey75")),
units = c("Baren/Desert",
"C4 Grassland",
"C3 Grassland",
"Small forest",
"Tall forest",
"Unclassifiable/Other"),
format = c("aDGVM")),
rules = SimpleHeightAdgvm2BiomeRules,
layers.needed = list( list(quantity = "vegcover_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
list(quantity = "vegcover_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
list(quantity = "canopyheight_std", operator = "+", layers = ".Tree", new.layer = "Tree"),
list(quantity = "canopyheight_std", operator = "+", layers = ".Grass", new.layer = "Grass")),
data.reference = "-",
published.reference = "-")
#####################################################################
########### BIOME CLASSIFICATION, GROWTH FORM #######################
#####################################################################
#' Rules to classify coarse tropical biomes
#'
#' No reference yet
#'
#' @param x Numerical vector of vegetation over values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-5, baren, C4 grassland, C3 grassland, woodland, shrubland)
#' @keywords internal
#' @author Simon Scheiter \email{Simon.Scheiter@@senckenberg.de}
GrowthFormAdgvm2BiomeRules <- function(x){
# BIOME 1 - Baren/Desert
if( as.numeric(x[['vegcover_std_Grass']])<=2 & as.numeric(x[['vegcover_std_Woody']])<=5) {return("Baren/Desert")}
# BIOME 2 - C4 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Woody']])<=5 & as.numeric(x[['vegcover_std_C3G']])<=as.numeric(x[['vegcover_std_C4G']])) {return("C4 Grassland")}
# BIOME 3 - C3 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Woody']])<=5 & as.numeric(x[['vegcover_std_C3G']])> as.numeric(x[['vegcover_std_C4G']])) {return("C3 Grassland")}
# BIOME 4 - Woodland
else if( as.numeric(x[['vegcover_std_Woody']])> 5 & as.numeric(x[['vegcover_std_Tree']])> as.numeric(x[['vegcover_std_Shrub']])) {return("Woodland")}
# BIOME 5 - Shrubland
else if( as.numeric(x[['vegcover_std_Woody']])> 5 & as.numeric(x[['vegcover_std_Tree']])<=as.numeric(x[['vegcover_std_Shrub']])) {return("Shrubland")}
# BIOME 6 - Remainder, Unclassified
else {
return("Unclassifiable/Other")
}
}
#' Meta-data describing a simple scheme for aDGVM2 output.
#'
#'\strong{GrowthFormAdgvm2BiomeSchemes} SS document here
#'
#' @rdname BiomeScheme-class
#' @export
#'
GrowthFormAdgvm2BiomeScheme <- new("Scheme",
new("Quantity",
id = "GrowthFormAdgvm2BiomeScheme",
name = "Growth Form aDGVM2 Biomes",
colours = grDevices::colorRampPalette(c("Baren/Desert" = '#cccccc',
"C4 Grassland" = '#fff700',
"C3 Grassland" = '#ffcf0f',
"Woodland" = '#94b6ff',
"Shrubland" = '#d6c100',
"Unclassifiable/Other" = "grey75")),
units = c("Baren/Desert",
"C4 Grassland",
"C3 Grassland",
"Woodland",
"Shrubland",
"Unclassifiable/Other"),
format = c("aDGVM")),
rules = GrowthFormAdgvm2BiomeRules,
layers.needed = list( list(quantity = "vegcover_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
list(quantity = "vegcover_std", operator = "+", layers = c(".Tree", ".Shrub"), new.layer = "Woody"),
list(quantity = "vegcover_std", operator = "+", layers = ".Shrub", new.layer = "Shrub"),
list(quantity = "vegcover_std", operator = "+", layers = ".Tree", new.layer = "Tree")),
data.reference = "-",
published.reference = "-")
#####################################################################
########### BIOME CLASSIFICATION, PHENOLOGY #########################
#####################################################################
#' Rules to classify coarse tropical biomes
#'
#' No reference yet
#'
#' @param x Numerical vector of vegetation over values for a particular location.
#' Certain fractions and quantities should have been pre-calculated.
#'
#' @return Biomes code (1-6, baren, C4 grassland, C3 grassland, woodland, evergreen forest, deciduous forest)
#' @keywords internal
#' @author Simon Scheiter \email{Simon.Scheiter@@senckenberg.de}
PhenologyAdgvm2BiomeRules <- function(x){
# BIOME 1 - Baren/Desert
if( as.numeric(x[['vegcover_std_Grass']])<=2 & as.numeric(x[['vegcover_std_Woody']])<=5) {return("Baren/Desert")}
# BIOME 2 - C4 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Woody']])<=5 & as.numeric(x[['vegcover_std_C3G']])<=as.numeric(x[['vegcover_std_C4G']])) {return("C4 Grassland")}
# BIOME 3 - C3 grassland
else if( as.numeric(x[['vegcover_std_Grass']])> 2 & as.numeric(x[['vegcover_std_Woody']])<=5 & as.numeric(x[['vegcover_std_C3G']])> as.numeric(x[['vegcover_std_C4G']])) {return("C3 Grassland")}
# BIOME 4 - Woodland
else if( as.numeric(x[['vegcover_std_Woody']])> 5 & as.numeric(x[['vegcover_std_Woody']])<=60) {return("Woodland")}
# BIOME 5 - Deciduous forest
else if( as.numeric(x[['vegcover_std_Woody']])>60 & as.numeric(x[['vegcover_std_Evergreen']])<=as.numeric(x[['vegcover_std_Raingreen']])) {return("Deciduous Forest")}
# BIOME 6 - Evergreen forest
else if( as.numeric(x[['vegcover_std_Woody']])>60 & as.numeric(x[['vegcover_std_Evergreen']])> as.numeric(x[['vegcover_std_Raingreen']])) {return("Evergreen Forest")}
# BIOME 7 - Remainder, Unclassified
else {
return("Unclassifiable/Other")
}
}
#' Meta-data describing a simple scheme for aDGVM2 output.
#'
#'\strong{PhenologyAdgvm2BiomeScheme} SS document here
#'
#'
#' @rdname BiomeScheme-class
#' @export
#'
PhenologyAdgvm2BiomeScheme <- new("Scheme",
new("Quantity",
id = "PhenologyAdgvm2BiomeScheme",
name = "Phenology aDGVM2 Biomes",
colours = grDevices::colorRampPalette(c("Baren/Desert" = '#cccccc',
"C4 Grassland" = '#fff700',
"C3 Grassland" = '#ffcf0f',
"Woodland" = '#94b6ff',
"Deciduous Forest" = '#9c6007',
"Evergreen Forest" = '#308a0a',
"Unclassifiable/Other" = "grey75")),
units = c("Baren/Desert",
"C4 Grassland",
"C3 Grassland",
"Woodland",
"Deciduous Forest",
"Evergreen Forest",
"Unclassifiable/Other"),
format = c("aDGVM")),
rules = PhenologyAdgvm2BiomeRules,
layers.needed = list( list(quantity = "vegcover_std", operator = "+", layers = ".Grass", new.layer = "Grass"),
list(quantity = "vegcover_std", operator = "+", layers = c(".Tree", ".Shrub"), new.layer = "Woody"),
list(quantity = "vegcover_std", operator = "+", layers = ".Evergreen", new.layer = "Evergreen"),
list(quantity = "vegcover_std", operator = "+", layers = ".Raingreen", new.layer = "Raingreen")),
data.reference = "-",
published.reference = "-")
#' Currently supported classification schemes
#'
#' This is a list of all classification Schemes defined by DGVMTools.
#'
#' @author Matthew Forrest \email{matthew.forrest@@senckenberg.de}
#' @export
#'
#'
#' @examples
#' \donttest{
#'
#' # In this example we derive and plot the Smith et al 2014 and the
#' # Forrest et al 2015 biome classifications
#'
#' # First define a Source
#' test.dir <- system.file("extdata", "LPJ-GUESS_Runs", "CentralEurope", package = "DGVMTools")
#' test.Source <- defineSource(name = "LPJ-GUESS run", dir = test.dir, format = GUESS)
#'
#' # Smith et al. 2014
#' Smith2014.biomes <- getScheme(source = test.Source, scheme = Smith2014BiomeScheme,
#' year.aggregate.method = "mean")
#' print(plotSpatial(Smith2014.biomes))
#'
#' # Forrest et al. 2014
#' Forrest2015.biomes <- getScheme(source = test.Source, scheme = Forrest2015BiomeScheme,
#' year.aggregate.method = "mean")
#' print(plotSpatial(Forrest2015.biomes))
#'
#' }
supported.classification.schemes <- c("Smith2014" = Smith2014BiomeScheme,
"Hickler2012" = Hickler2012BiomeScheme,
"Forrest2015" = Forrest2015BiomeScheme,
"DevMegaBiomes" = DevMegaBiomeScheme,
"FPCMegaBiomes" = FPCMegaBiomeScheme,
"MeditBiomes" = MeditBiomeScheme,
"FireMIPBiomes" = FireMIPBiomeScheme,
"aDGVMBiomes" = aDGVMBiomeScheme,
"SimpleAdgvm2Biomes" = SimpleAdgvm2BiomeScheme,
"SimpleHeightAdgvm2Biomes" = SimpleHeightAdgvm2BiomeScheme,
"GrowthFormAdgvm2Biomes" = GrowthFormAdgvm2BiomeScheme,
"PhenologyAdgvm2Biomes" = PhenologyAdgvm2BiomeScheme)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.