Skip to content

A spatial selection optimization algorithm in ForSysR

License

Notifications You must be signed in to change notification settings

forsys-sp/patchmax

Repository files navigation

Patchmax

Patchmax is a computational module designed to explore spatially explicit landscape treatment projects. The package can be used to prioritize treatment locations on relatively small landscapes (project level implementation, 1,000 ha) to large landscapes (national forests to multi-regional planning efforts, 1 million ha). Although patchmax was originally designed for hazardous fuel treatment planning in forested systems, it can be applied to fiber production, habitat restoration, and other resource management problems. This version of Patchmax is based on a R6 objects and utilizes Djistra’s algorithm to sequence stands within patches based on both adjacency and distance.

Dependences: R (>= 4.0.3) and packages (R6, igraph, dplyr, sf, furrr, purrr, proxy, cppRouting)

Installation

Patchmax package can be installed from GitHub using the following code.

if (!require(remotes)) install.packages("remotes")
remotes::install_github("forsys-sp/patchmax")

Usage

Stand treatment units are represented as polygons in a spatial vector format. Each polygon represents a different treatment unit with numerous attributes that can be used to prioritize or constrain patch construction. To start, let’s load some example data included with patchmax. To keep things simple, we focus only a subset of the entire study area. Further below, we’ll set up a scenairo where we create several patches in sequence that maximize priority p4 up to a patch size of 1000 ha and a maximum cost of $50000

library(dplyr)
library(sf)
library(purrr)

geom <- patchmax::test_forest %>% 
  filter(row > 20, row <= 40, col > 20, col <= 40)

geom %>% 
  select(matches('p[0-9]|t[0-9]|b[0-9]|m[0-9]|c[0-9]')) %>%
  plot(max.plot = 20, border=NA)

We can combined these data to create additional fields. For example, let’s create a new field called cost, which we’ll use later as a secondary constraint building patches. In this example, treatment costs range between 500 and 5000 dollars per 100 ha stand.

geom <- geom %>% mutate(cost = ((p2 + p4 - c1) * 1000) + 3000)
plot(geom[,'cost'], border=NA)

Patchmax is written as R6 class, which uses a syntax that differs from functional programming design used in most R functions. We first create a patchmax object called pm using the new method in the patchmax class and specify five base parameters that required in every Patchmax run: the stand geometry, the fields names for the stand id, objective, and area, and finally the maximum area allowed in a patch.

pm <- patchmax$new(
  geom = geom, 
  id_field = 'id', 
  objective_field = 'p4', 
  area_field = 'ha', 
  area_max = 2500)

The core purpose of patchmax is build spatially contiguous patches that maximizes some objective given some maximum size constraint. The example below shows how this is done over a series of steps: (1) patchmax searches for the best place, (2) builds that patch, (3) plots the patch, (4) records the patch, (5) describes the patch statistics.

pm$search()
pm$record()
pm$plot()

Note that the same set of sequence of steps can be chained together into a single line: pm$search()$build()$plot(). This is a distinct feature of R6 class objects that works similar to piping |>.

To get a better sense of how the patch is selected, let’s look at the search results in more detail. The plot below shows the patch scores using each stand as a potential seed. Note how the stands recorded in the previous patch are excluded. While the search plot looks similar to stand plot of the priority p4, the values represent the potential objective score of a patch if it were built from that location. In this sense, patchmax works similar to a moving window spatial analysis

pm$search(plot = T)

Next we’ll change a few additional parameters and see how this affects the search. Notice how two large blocks of the landscape are excluded due to the new treatment threshold.

pm$threshold = 't1 == 1'
pm$search(plot = T)

Next, let’s add a secondary constraint that limits the overall cost of each patch to 15000. Note how this suppresses the search_out scores substantially; many of the potential patch locations that were able to produce high quality patches are now blue. This change is the result of the new cost constraint limiting patch sizes in many areas of the landscape from growing more than a few stands in size, hence the lower scores.

pm$constraint_field = 'cost'
pm$constraint_max = 15000
pm$search(plot = T, verbose =T)

Adding a minimum patch size constrains potential projects further and removes additional sections of the landscape from consideration since no viable patches exist.

pm$area_min = 500
pm$search(plot = T)

As a final step, we’ll reset the patchmax run and use the simulate method to identify the 10 highest prioirty patches given the area, cost and threshold constraints.

pm$reset()
pm$simulate(10)
pm$plot()

pm$patch_stats
##    patch_id seed area coverage objective constraint excluded
## 1         1 3033 1200     1800       7.8      14230       33
## 2         2 3338 1300     2200       7.7      14380       41
## 3         3 2233 1100     1700       5.2      14920       35
## 4         4 2632  800      800       5.1      13520        0
## 5         5 3129 1600     1700       4.4      14570        6
## 6         6 3734  800     1200       4.3      13270       33
## 7         7 2630  700      700       4.2      14770        0
## 8         8 3840  800      800       4.0      13850        0
## 9         9 2923  600      600       3.6      14080        0
## 10       10 2926  800      800       3.6      14810        0

Getting help

If you have any questions about the patchmax package or suggestions for improving it, please post an issue on the code repository.

Studies

Patchmax builds on an earlier implementation as described in Belavenutti et al. 2022 which pioneered the use of network search algorithms to prioritize patches. The current version was rewritten as an R6 object class and uses Dijstra’s algorithm over breath first search in evaluating patches.

Belavenutti, Pedro, Alan A. Ager, Michelle A. Day, and Woodam Chung. 2022. Designing forest restoration projects to optimize the application of broadcast burning. Ecological Economics.s