Zonation 5 is a spatial prioritization software that can be used to identify priority areas to support conservation planning, land use planning, ecological impact avoidance and other similar tasks. The software uses spatial raster data on the distributions of individual biodiversity features (species, habitats, ecosystem services etc.) to identify which locations in a landscape are most important for retaining biodiversity. Zonation can account for local habitat quality and ecological connectivity together with costs, threats and different land tenure, thus providing a quantitative method for spatial planning that enhances the persistence of biodiversity in the long term.
We took all of the rasters prepared earlier and fed these into the Zonation 5 software. This should provide a relative ranking for locations from highest to lowest for the purposes of biodiversity conservation.
Note: Zonation 5 is usually a standalone application. Here, I have enabled running of Zonation from R, using command line functions. This way we can adjust and automatically run Zonation, reading from data in R.
Here we calculate the overlap of the top % of conservation values with these other layers:
Protected areas
Private land
Human Footprint (HFP)
Freshwater habitats
Lakes
Ponds
Streams
Wetlands
Riparian
Code
# Function for converting Zonation output to boolean based on percentage (in top XX%)rankmap <-here(output_dir , "rankmap.tif") %>%rast() %>%project(project_crs)#' Only keep top or bottom cell values by quantile #'#' @param x SpatRaster #' @param prob Quantile between 0 and 1#' @param direction "top" or "bottom", for direction of keep / discard cell values#'#' @returns SpatRaster#' @exportremove_by_quantile <-function(x, prob, direction ="top") { val <- x %>%values() %>%quantile(probs = prob, na.rm = T) min_val <- x %>%values() %>%min(na.rm = T) max_val <- x %>%values() %>%max(na.rm = T)if(direction =="top") { m <-matrix(c( min_val, val, NA, val, max_val, 1 ), ncol =3, byrow = T) } elseif (direction =="bottom") { m <-matrix(c( min_val, val, 1, val, max_val, NA ), ncol =3, byrow = T) } mask_quantile <- x %>%classify(m,, include.lowest = T) mask_quantile * x}#' Provide ratio of overlap between two rasters (in terms of NA vs nonNA)#' raster_overlap_ratio <-function(top_rast, area_rast) { overlap_res <- (top_rast * area_rast) top_cell_count <- top_rast %>% terra::global(fun="notNA") overlap_cell_count <- overlap_res %>% terra::global(fun="notNA") overlap_ratio <- (overlap_cell_count / top_cell_count) %>%as.numeric()return(overlap_ratio)}# Protected Areas from JDbowen_protectedareas_rast <- bowen.biodiversity.webapp::bowen_protectedareas %>% bowen.biodiversity.webapp::bowen_rasterize()# Private Landbowen_mask <-rast(here("inst/extdata/bowen_mask.tif"))bowen_parcelmap_rast <- bowen.biodiversity.webapp::bowen_parcelmap %>%st_cast("MULTIPOLYGON") %>%# Need this due to MULTISURFACE - see: https://gis.stackexchange.com/questions/389814/r-st-centroid-geos-error-unknown-wkb-type-12 filter(OwnerType =="Private") %>% bowen.biodiversity.webapp::bowen_rasterize()# Freshwater Habitats fw_rast_paths <-c(here("inst/extdata/habitats/lakes.tif"),here("inst/extdata/habitats/ponds.tif"),here("inst/extdata/habitats/riparian.tif"),here("inst/extdata/habitats/wetlands.tif"),here("inst/extdata/habitats/streams.tif"))fw_rast_stack <-lapply(fw_rast_paths, rast) %>%rast()fw_rast_dissolve <- fw_rast_stack %>%sum(na.rm = T) # Human Footprint (classified)bowen_hfp <-here("inst/extdata/habitats/bowen_human_footprint_recl.tif") %>%rast()bowen_hfp_low <- bowen_hfp %>%classify(cbind(3, NA)) %>%classify(cbind(2, NA))bowen_hfp_med <- bowen_hfp %>%classify(cbind(3, NA)) %>%classify(cbind(1, NA))bowen_hfp_high <- bowen_hfp %>%classify(cbind(2, NA)) %>%classify(cbind(1, NA))# Overlap calculation overlap_stats <-function(top_rast) {data.frame(protectedareas_overlap =raster_overlap_ratio(top_rast, bowen_protectedareas_rast),privatelands_overlap =raster_overlap_ratio(top_rast, bowen_parcelmap_rast),freshwater_overlap =raster_overlap_ratio(top_rast, fw_rast_dissolve),hfp_low_overlap =raster_overlap_ratio(top_rast, bowen_hfp_low),hfp_med_overlap =raster_overlap_ratio(top_rast, bowen_hfp_med),hfp_high_overlap =raster_overlap_ratio(top_rast, bowen_hfp_high) )}quants <-seq(from =0, to =1, by =0.1)overlap_results <-foreach(quant = quants, .combine ="rbind") %do% { rankmap %>%remove_by_quantile(quant) %>%overlap_stats() %>%mutate("removed_bottom_quantile"= quant) %>%relocate("removed_bottom_quantile")}# Visualize output as table for overlap % knitr::kable(overlap_results)
removed_bottom_quantile
protectedareas_overlap
privatelands_overlap
freshwater_overlap
hfp_low_overlap
hfp_med_overlap
hfp_high_overlap
0.0
0.3446264
0.5810277
0.4756258
0.0329381
0.6519857
0.3150762
0.1
0.3793392
0.6041405
0.4962359
0.0305312
0.6382267
0.3312422
0.2
0.3780287
0.6184427
0.5088215
0.0183486
0.6334980
0.3481534
0.3
0.3672043
0.6387097
0.5174731
0.0182796
0.6196237
0.3620968
0.4
0.3936637
0.6483689
0.5269762
0.0153701
0.6286073
0.3560226
0.5
0.4136244
0.6605194
0.5333082
0.0112909
0.6398193
0.3488897
0.6
0.4322672
0.6806209
0.5555033
0.0075259
0.6387582
0.3537159
0.7
0.4548306
0.6894605
0.5777917
0.0037641
0.6317440
0.3644918
0.8
0.4553151
0.6782690
0.6114770
0.0037629
0.5879586
0.4082785
0.9
0.5169173
0.6409774
0.6390977
0.0056391
0.5469925
0.4473684
1.0
NaN
NaN
NaN
NaN
NaN
NaN
Overlap Statistics - Polygon on Raster
Here we calculate the overlap of the top % of conservation values with these other layers:
Protected areas
From John Dowler’s Protected Areas, vs Bowen Island Municipality Protected Areas polygons used for February 1 ver.
Contains main municipal parks, provincial parks, federal parks (both JD and BIM ver.)
Addition of covenants, park land exchanges, small municipal parks in JD ver.
Slightly higher than original February 1 ver. (~18% vs ~21%)
Protected areas polygons / Bowen Island full polygon (inc. Hutt Island) = 0.2149664
Protected area extent proportion of Bowen Island using raster method = 0.2189496
Private land
“Private” - Defined as “Private” in BC ParcelMap polygons
“Other” - Defined as anything other than “Private” in BC ParcelMap polygons
Used to see how much of BC ParcelMap polygons are not Private lands
Does not add up to 100%, since there are large areas that are not included in BC ParcelMap
Private lands polygons / Bowen Island full polygon (inc. Hutt Island) = 0.4398566
Private lands extent proportion of Bowen Island using raster method = 0.4398923
Human Footprint (HFP)
Proportion of each HFP category (low, medium, high) in the top XX% of biodiversity values
Should add up to 100%
Freshwater habitats
Lakes
Ponds
Streams
Wetlands
Riparian
Code
# Function for converting Zonation output to boolean based on percentage (in top XX%)rankmap <-here(output_dir , "rankmap.tif") %>%rast() %>%project(project_crs)#' Only keep top or bottom cell values by quantile #'#' @param x SpatRaster #' @param prob Quantile between 0 and 1#' @param direction "top" or "bottom", for direction of keep / discard cell values#'#' @returns SpatRaster#' @exportremove_by_quantile <-function(x, prob, direction ="top") { val <- x %>%values() %>%quantile(probs = prob, na.rm = T) min_val <- x %>%values() %>%min(na.rm = T) max_val <- x %>%values() %>%max(na.rm = T)if(direction =="top") { m <-matrix(c( min_val, val, NA, val, max_val, 1 ), ncol =3, byrow = T) } elseif (direction =="bottom") { m <-matrix(c( min_val, val, 1, val, max_val, NA ), ncol =3, byrow = T) } mask_quantile <- x %>%classify(m,, include.lowest = T) mask_quantile * x}#' Rasterize to Bowen Island Maskbowen_rasterize_cover <-function(sf) { bowen_island_mask <-here("inst/extdata/bowen_mask.tif") %>%rast() %>%project(bowen.biodiversity.webapp::project_crs) output <- sf %>% terra::vect() %>%# Change to SpatVector for rasterization terra::project(bowen.biodiversity.webapp::project_crs) %>%# Reproject to the mask CRS terra::rasterize(bowen_island_mask,cover = T, # Return proportion of cell covered by polygon background =NA) # Rasterize to match mask, set background values to NA}#' Provide ratio of overlap between two rasters (in terms of NA vs nonNA)raster_overlap_ratio <-function(top_rast, area_rast) { overlap_res <- (top_rast * area_rast) top_cell_count <- top_rast %>%global("sum", na.rm = T) overlap_cell_values <- overlap_res %>%values(na.rm = T) overlap_cell_area <-overlap_cell_values %>%sum() overlap_ratio <- (overlap_cell_area / top_cell_count) %>%as.numeric()return(overlap_ratio)}# Bowen entire areabowen_island <-st_read(here("data-raw/bowen_island_shoreline_w_hutt.gpkg"), layer ="bowen_island_shoreline_w_hutt__bowen_islands")
Reading layer `bowen_island_shoreline_w_hutt__bowen_islands' from data source
`/home/jay/Programming_Projects/bowen.biodiversity.webapp/data-raw/bowen_island_shoreline_w_hutt.gpkg'
using driver `GPKG'
Simple feature collection with 11 features and 1 field
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 4001956 ymin: 2020764 xmax: 4013988 ymax: 2028901
Projected CRS: NAD83 / Statistics Canada Lambert
Code
# Protected Areas from JDbowen_protectedareas_include <- bowen.biodiversity.webapp::bowen_protectedareas %>%filter(type !="Agricultural Land Reserve") # Remove ALR# Protected Areas from Bowen Island Municipality bowen_protectedareas_2 <-st_read(here("data-raw/archive/bowen_island_protectedareas/BM_PROTECTED_AREAS.shp")) %>%filter(NAME !="Old Growth Management Area")
Reading layer `BM_PROTECTED_AREAS' from data source
`/home/jay/Programming_Projects/bowen.biodiversity.webapp/data-raw/archive/bowen_island_protectedareas/BM_PROTECTED_AREAS.shp'
using driver `ESRI Shapefile'
Simple feature collection with 61 features and 2 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 468632.2 ymin: 5464739 xmax: 476690.7 ymax: 5472342
Projected CRS: NAD83 / UTM zone 10N
Code
# JD protected areas is more complete, with smaller municipal parks, covenants, and park land exchangesbowen_protectedareas_rast <- bowen_protectedareas_include %>%bowen_rasterize_cover()# Check with polygon / polygon area calculations for full Bowen Islandsum(st_area(bowen_protectedareas_include)) /sum(st_area(bowen_island)) # 0.2149664
# Private Landbowen_mask <-rast(here("inst/extdata/bowen_mask.tif"))bowen_parcelmap_priv <- bowen.biodiversity.webapp::bowen_parcelmap %>%st_cast("MULTIPOLYGON") %>%# Need this due to MULTISURFACE - see: https://gis.stackexchange.com/questions/389814/r-st-centroid-geos-error-unknown-wkb-type-12 filter(OwnerType =="Private")bowen_parcelmap_rast <- bowen_parcelmap_priv %>%bowen_rasterize_cover()# Check with polygon / polygon area calculations for full Bowen Island sum(st_area(bowen_parcelmap_priv)) /sum(st_area(bowen_island)) # 0.4398566