knitr::opts_chunk$set( #collapse = TRUE, #comment = "#>", message = F )
suppressPackageStartupMessages({ library(tidyverse) library(here) library(glue) library(raster) select = dplyr::select library(sf) library(leaflet) library(RColorBrewer) library(rasterVis) library(prioritizr) # install.packages("prioritizr") #library(bbnj) # devtools::install_local(here::here(), force=T) devtools::load_all() }) if (basename(getwd())!="vignettes") setwd(here("vignettes")) # set rainbow color palette pal <- colorRampPalette(brewer.pal(11, "Spectral")) cols <- rev(pal(255))
The core datasets for developing BBNJ scenarios have been made available within the R package using the data-raw/create_data.R script, which also clips input datasets to the high seas, for lazy loading within R. For programs external to R, usable formats (*.tif, *.shp) have been placed into the data-raw/ folder online, which you can access by downloading the latest bbnj master.zip.
# view list of all datasets in bbnj R package #data(package="bbnj") # get detailed help on any dataset # ?r_pu_id # use lazily loaded dataset, not showing in environment r_pu_id # explicitly attach to environment data("r_pu_id")
Using half-degree global raster (resolution of AquaMaps, GFW, ...).
# show planning unit id raster plot(r_pu_id, col = cols, main="pu_id")
Get area for planning units ($km^2$):
r_pu_area <- area(r_pu_id) %>% # in km2 mask(r_pu_id) plot(r_pu_area, col = cols, main="pu_area (km2)")
Rescale area for being able to set planning unit budgets to percentages of the global high seas:
A <- cellStats(r_pu_area, "sum") r_pu_areas <- r_pu_area / A #cellStats(r_pu_areas, "sum") # 1 plot(r_pu_areas, col = cols, main="pu_areas (sums to 1)")
All the species distribution data was generously provided as comma-seperated value (csv) files in a zip package aquamaps_ver0816c.zip by Kristin Kaschner and Cristina Garilao to Ben Best ben@ecoquants.com on Jun 21, 2018 from the extensive work available at http://AquaMaps.org to be fully cited [@kaschnerAquaMapsPredictedRange2016] whenever used. For details on generating indicators, see Calculate Indicators • gmbi:
Note that a probability ≥ 0.5 was used to convert AquaMaps relative environmental suitability (RES) from continuous [0 - 1] to binary [0,1] [@kleinShortfallsGlobalProtected2015; @oharaAligningMarineSpecies2017] for generating these two indicators:
nspp: number of species, ie species richness
rls: Red List Sum (RLS)
The Red List Sum (RLS) is the numerator from the Red List Index (RLI) ([@butchartImprovementsRedList2007; @juslenApplicationRedList2016]:
$$RLS = \sum_{i=1}^{n_{spp}} w_i$$
We will use only the numerator, the Red List Sum (RLS), of the Red List Index (RLI) to quantify the "endangeredness" of a cell without dilution from being in a species-rich place as the RLI does when averaging the extinction risk for all assessed species. For more details see Calculate extinction risk - Calculate Indicators • gmbi.
These indicators were calculated for all species as well as taxonomic groups defined in Assign taxonomic groups - Calculate Indicators • gmbi.
With rasters from R package marinebon/gmbi, mask rasters to high seas planning units and save into this R package:
names(s_bio_gmbi)
nspp, all taxar_nspp_all <- raster(s_bio_gmbi, "nspp_all") plot(r_nspp_all, col = cols, main="nspp, all taxa")
nspp, all taxa, area scaledr_nspp_all_as <- rescale_raster(r_nspp_all, multiply_area=T) # "bio_nspp" plot(r_nspp_all_as, col = cols, main="nspp, all taxa, area scaled")
nspp, by taxonomic groupgrps_nspp <- names(s_bio_gmbi) %>% str_subset("^nspp_") %>% str_subset("_all$", negate=T) s_bio_nspp_grps <- raster::subset(s_bio_gmbi, grps_nspp) names(s_bio_nspp_grps) <- names(s_bio_nspp_grps) %>% str_replace("nspp_", "") plot(s_bio_nspp_grps, col = cols)
rls, all taxar_rls_all <- raster(s_bio_gmbi, "rls_all") plot(r_rls_all, col = cols, main="rls, all taxa")
rls, all taxa, area scaledr_rls_all_as <- rescale_raster(r_rls_all, multiply_area=T) plot(r_rls_all_as, col = cols, main="rls, all taxa, area scaled")
rls, by taxonomic groupgrps_rls <- names(s_bio_gmbi) %>% str_subset("^rls_") %>% str_subset("_all$", negate=T) s_bio_rls_grps <- raster::subset(s_bio_gmbi, grps_rls) names(s_bio_rls_grps) <- names(s_bio_rls_grps) %>% str_replace("rls_", "") plot(s_bio_rls_grps, col = cols)
Count of seamounts (Kim & Wessel, 2011) in half-degree cells:
plot(s_phys_seamounts, col = cols, main="s_phys_seamounts")
Area (km2) of 1 thru 11 classes of benthic seascapes (Harris & Whiteway, 2009):
plot(s_phys_scapes, col = cols)
Raster stack from Global Fishing Watch analysis of high seas (Sala et al, 2018) for half-degree raster of high seas (year of analysis: 2016).
names(s_fish_gfw) plot(s_fish_gfw, col = cols)
Assuming places fished have the least profit, gap fill with minimum value:
r_fish_gfw.profit <- raster(s_fish_gfw, "mean_scaled_profits") %>% gap_fill_raster() r_fish_gfw.profit.subsidies <- raster(s_fish_gfw, "mean_scaled_profits_with_subsidies") %>% gap_fill_raster() plot(r_fish_gfw.profit.subsidies, col=cols, main="r_gfw_profit.subsidies")
Fisheries could be included into the optimization in at least a couple ways:
Fisheries as Planning Unit Cost (Minimize). By minimizing the planning unit cost, conservation targets are maximized.
Fisheries as Conservation Target (Maximize Inverse). To reduce friction with fishing industry the maximum profit areas are to be minimized. To achieve this on the conservation target side of the optimization the inverse of the original profit layers is to be used, which can take the form:
$$v_{cell} = 1 - \frac{v_{cell}}{\max(v) - \min(v)}$$
r_fish_gfw.profit.subsidies_inv <- rescale_raster(r_fish_gfw.profit.subsidies, inverse=T) #, log=T) hist(r_fish_gfw.profit.subsidies, main="r_gfw_profit.subsidies") hist(r_fish_gfw.profit.subsidies_inv, main="r_gfw_profit.subsidies_inv") plot(r_fish_gfw.profit.subsidies_inv, col=cols, main="r_gfw_profit.subsidies_inv")
Raster stack from UBC (Cheung, Lam et al; in draft) of maximum catch potential (MCP; landings in metric tons) of more than 1,000 fish and invertebrates species for \code{mcp_2004} (average 1995 to 2014) and \code{mcp_2050} (average 2041 to 2060 under 'business as usual' climate change scenario GFDL 8.5).
plot(s_fish_ubc, col = cols)
s_fish_ubc_inv <- rescale_stack(s_fish_ubc, inverse=T) plot(s_fish_ubc_inv, col = cols)
Maximize diversity of species and habitats, given a budget of 10% of the high seas.
p01_features <- stack( r_nspp_all_as, r_rls_all_as, rescale_raster(s_phys_seamounts), rescale_raster(r_phys_vents), rescale_stack(s_phys_scapes)) names(p01_features) <- c( "bio_nspp", "bio_rls", "phys_seamounts", "phys_vents", glue("phys_scape{1:11}")) # hist(r_nspp_all_as); hist(r_rls_all_as); hist(rescale_raster(s_phys_seamounts)) p01_sum <- raster::stackApply(p01_features, rep(1,nlayers(p01_features)), sum) %>% mask(r_pu_id) plot(p01_sum, col=cols) #plot(r_pu_areas, col = cols, main="pu_areas (sums to 1)") p01 <- problem(r_pu_areas, p01_features) %>% add_max_utility_objective(budget = 0.1) %>% # 10% of total high seas area add_gurobi_solver() # DEBUG devtools::load_all() p01_sol <- solve_log(p01, redo=F) plot(p01_sol, col = c("grey90", "darkgreen"), main = "p01 solution") # area of solution cellStats(r_pu_areas * p01_sol, "sum") # calculate how well features are represented in the solution feature_representation(p01, p01_sol) # Error in feature_representation(p01, p01_sol) : # planning units with NA cost data have non-zero allocations in the argument to solution
Strategy:
add_max_utility_objective(budget = 0.1) to determine max relative targets for:add_max_features_objective(budget = 0.1) + add_relative_targets(c(0.3, 0.3, 0))add_feature_weights() to balance outp01_diagnostics <- problem_diagnostics(r_pu_areas, p01_features, budget=0.1) p01_diagnostics #View(p01_diagnostics)
If relative target exceeds amount available, ie p01_diagnostics$rel_each, then target gets essentially dropped, so set to some compromise between full solution (rel_all) and max amount if just that feature chosen (rel_each) as the mean of the two. Do not excessively weight other features, so cap to 0.2 or similar with min.
p02_targets <- p01_diagnostics %>% mutate( rel_mean = (rel_all + rel_each) / 2, target = map_dbl(rel_mean, function(x) min(x, 0.2))) p02_targets p02 <- problem(r_pu_areas, p01_features) %>% add_max_features_objective(budget = 0.1) %>% add_relative_targets(pull(p02_targets, target)) %>% add_gurobi_solver() p02_sol <- solve_log(p02, redo=F) # plot solution plot(p02_sol, col = c("grey90", "darkgreen"), main = "p02 solution") # area of solution cellStats(r_pu_areas * p02_sol, "sum") # calculate how well features are represented in the solution feature_representation(p02, p02_sol)
Maximize overall biodiversity, given a budget of 10% of all high seas area.
Try to include missed phys_scape1 and phys_scape2 by adding weight.
p03 <- problem(r_pu_areas, p01_features) %>% add_max_features_objective(budget = 0.1) %>% add_relative_targets(pull(p02_targets, target)) %>% add_feature_weights(c(10, 10, 10, 10, 3, 3, 2, 2, rep(1, 7))) %>% add_gurobi_solver() p03_sol <- solve_log(p03, redo=F) plot(p03_sol, col = c("grey90", "darkgreen"), main = "p03 solution") cellStats(r_pu_areas * p03_sol, "sum") feature_representation(p03, p03_sol) problem_diagnostics(r_pu_areas, p01_features, budget=0.3, pfx="p05")
p01_diagnostics <- problem_diagnostics(r_pu_areas, p01_features, budget=0.1) p01_diagnostics #View(p01_diagnostics)
Add clumping.
From the marxan manual 1.8.10.pdf (p. 22-23):
3.2.1.1.2 Boundary Length Modifier As a very rough guide, a good starting place for the BLM is to scale it such that the largest boundary between planning units becomes a similar order of magnitude to the most expensive planning unit. For instance, if your highest planning unit cost is 100 and your longest boundary is 1000, you may want to start the BLM at 0.1. Note that it is usually best to explore a range of values that are separated using a fixed multiplier; e.g., 0.04, 0.2, 1, 5, 25 – where in this example, these values are each multiplied by 5. Typically, the values are increased exponentially or by orders of magnitude in order to sample a range of values and choose one that balances the order of magnitude of competing terms of the objective function.
Using same formulation as p01 + BLM.
# set clumping parameter based on BLM advice in Marxan manual, exp't with p01 blm <- cellStats(r_pu_areas, "max") / 0.5 * 10000 blm p04 <- problem(r_pu_areas, p01_features) %>% add_max_utility_objective(budget = 0.1) %>% add_boundary_penalties(blm, 1) %>% add_gurobi_solver() p04_sol <- solve_log(p04, redo=F) plot(p04_sol, col = c("grey90", "darkgreen"), main = "p04 solution") cellStats(r_pu_areas * p04_sol, "sum") feature_representation(p04, p04_sol)
Maximize diversity of species and habitats, given a budget of 30% of the high seas.
p05 <- problem(r_pu_areas, p01_features) %>% add_max_utility_objective(budget = 0.3) %>% add_gurobi_solver() p05_sol <- solve_log(p05, redo=F) plot(p05_sol, col = c("grey90", "darkgreen"), main = "p05 Solution") cellStats(r_pu_areas * p05_sol, "sum") feature_representation(p05, p05_sol)
Goal: Protect habitats with strong focus on minimizing impacts to fishing profits.
p06_features <- stack( r_fish_gfw.profit.subsidies_inv, raster(s_fish_ubc_inv, "mcp_2004"), rescale_raster(s_phys_seamounts), rescale_raster(r_phys_vents), rescale_stack(s_phys_scapes)) names(p06_features) <- c( "fish_profit.subs", "fish_mcp.now", "phys_seamounts", "phys_vents", glue("phys_scape{1:11}")) # hist(r_nspp_all_as); hist(r_rls_all_as); hist(rescale_raster(s_phys_seamounts)) p06_sum <- raster::stackApply(p06_features, rep(1,nlayers(p06_features)), sum) %>% mask(r_pu_id) plot(p06_sum, col=cols) p06 <- problem(r_pu_areas, p06_features) %>% add_max_utility_objective(budget = 0.1) %>% # 10% of total high seas area add_gurobi_solver() p06_sol <- solve_log(p06, redo=F) plot(p06_sol, col = c("grey90", "darkgreen"), main = "p06 solution") cellStats(r_pu_areas * p06_sol, "sum") feature_representation(p06, p06_sol) p06_diagnostics <- problem_diagnostics(r_pu_areas, p06_features, budget=0.1) p06_diagnostics
Strategy:
add_max_utility_objective(budget = 0.1) to determine max relative targets for:add_max_features_objective(budget = 0.1) + add_relative_targets(c(0.3, 0.3, 0))add_feature_weights() to balance outGoal: Protect habitats with strong focus on minimizing impacts to fishing profits.
p07 <- problem(r_pu_areas, p06_features) %>% add_max_utility_objective(budget = 0.3) %>% # 10% of total high seas area add_gurobi_solver() p07_sol <- solve_log(p07, redo=F) plot(p07_sol, col = c("grey90", "darkgreen"), main = "p07 solution") cellStats(r_pu_areas * p07_sol, "sum") feature_representation(p07, p07_sol) p07_diagnostics <- problem_diagnostics(r_pu_areas, p06_features, budget=0.3, pfx="p07") p07_diagnostics
select = dplyr::select read_csv("~/github/gmbi/data-raw/spp_iucn.csv") %>% group_by(iucn_criteria) %>% summarize(n = n()) %>% arrange(desc(n)) %>% View() # table(useNA="always") #iucn_category, iucn_criteria, iucn_population_trend
Integrated “kitchen sink”
p08_features <- stack( r_nspp_all_as, r_rls_all_as, r_fish_gfw.profit.subsidies_inv, raster(s_fish_ubc_inv, "mcp_2004"), raster(s_fish_ubc_inv, "mcp_2050"), rescale_raster(s_phys_seamounts), rescale_raster(r_phys_vents), rescale_stack(s_phys_scapes)) names(p08_features) <- c( "bio_nspp", "bio_rls", "fish_profit.subs", "fish_mcp.now", "fish_mcp.future", "phys_seamounts", "phys_vents", glue("phys_scape{1:11}")) p08_features <- stack( raster(s_bio_gmbi, "nspp_all") %>% rescale_raster(multiply_area=T), raster(s_bio_gmbi, "rls_all") %>% rescale_raster(multiply_area=T), raster(s_fish_gfw, "mean_scaled_profits_with_subsidies") %>% gap_fill_raster() %>% rescale_raster(inverse=T), rescale_stack(s_fish_ubc, inverse=T), rescale_raster(s_phys_seamounts), rescale_raster(r_phys_vents), r_mine_claim, rescale_stack(s_phys_scapes)) names(p08_features) <- c( "bio_nspp", "bio_rls", "fish_profit.subs", "fish_mcp.2004", "fish_mcp.2050", "phys_seamounts", "phys_vents", "mine_claim", glue("phys_scape.{1:11}")) p08 <- problem(r_pu_areas, p08_features) %>% add_max_utility_objective(budget = 0.1) %>% # 10% of total high seas area add_gurobi_solver() p08_sol <- solve_log(p08, redo=F) plot(p08_sol, col = c("grey90", "darkgreen"), main = "p08 solution") cellStats(r_pu_areas * p08_sol, "sum") feature_representation(p08, p08_sol) p08_diagnostics <- problem_diagnostics(r_pu_areas, p08_features, budget=0.1, redo=F) p08_diagnostics
Maximize overall biodiversity, given a budget of 10% of all high seas area.
Try to include missed phys_scape1 and phys_scape2 by adding weight.
p09 <- problem(r_pu_areas, p01_features) %>% add_max_utility_objective(budget = 0.1) %>% add_feature_weights(c(100, 100, 10, 10, rep(1, 11))) %>% add_gurobi_solver() p09_sol <- solve_log(p09, redo=T) plot(p09_sol, col = c("grey90", "darkgreen"), main = "p09 solution") cellStats(r_pu_areas * p09_sol, "sum") feature_representation(p09, p09_sol)
Add clumping.
From the marxan manual 1.8.10.pdf (p. 22-23):
3.2.1.1.2 Boundary Length Modifier As a very rough guide, a good starting place for the BLM is to scale it such that the largest boundary between planning units becomes a similar order of magnitude to the most expensive planning unit. For instance, if your highest planning unit cost is 100 and your longest boundary is 1000, you may want to start the BLM at 0.1. Note that it is usually best to explore a range of values that are separated using a fixed multiplier; e.g., 0.04, 0.2, 1, 5, 25 – where in this example, these values are each multiplied by 5. Typically, the values are increased exponentially or by orders of magnitude in order to sample a range of values and choose one that balances the order of magnitude of competing terms of the objective function.
Using same formulation as p01 + BLM.
# set clumping parameter based on BLM advice in Marxan manual, exp't with p01 blm <- cellStats(r_pu_areas, "max") / 0.5 * 10000 blm p04 <- problem(r_pu_areas, p01_features) %>% add_max_utility_objective(budget = 0.1) %>% add_boundary_penalties(blm, 1) %>% add_gurobi_solver() p04_sol <- solve_log(p04, redo=F) plot(p04_sol, col = c("grey90", "darkgreen"), main = "p04 solution") cellStats(r_pu_areas * p04_sol, "sum") feature_representation(p04, p04_sol)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.