Guide to Disturbance Matrices in rcbm4

Vinicius Manvailer

2026-01-06

Introduction

Welcome! This guide is designed to help you work with disturbance matrices (DMs) within the rcbm4 package. In the Carbon Budget Model (CBM), disturbance matrices define how carbon is transferred between ecosystem pools, or to the atmosphere, as a result of a disturbance event like a wildfire, harvest, or insect infestation.

In this vignette, we’ll walk through a complete workflow:

  1. Querying: How to find and retrieve existing disturbance matrices from the CBM defaults database.
  2. Visualizing: How to create insightful alluvial diagrams to understand the carbon transfers within a DM.
  3. Adding: How to create and add new, custom disturbance matrices to a CBM database for your own simulations.

Let’s get started!

First, let’s load the rcbm4 package, along with data.table for data manipulation.

library(rcbm4)
library(data.table)

1. Querying Disturbance Matrices

The get_disturbance_matrices() function is your primary tool for fetching DMs from the CBM defaults database. It’s powerful because it allows you to search using various criteria, from general disturbance groups to specific names or IDs.

Let’s try a simple query to find all disturbance matrices related to “Wildfire”.

wildfire_dms <- get_disturbance_matrices(
  disturbance_type_names = "Wildfire"
)

message(paste("Found", nrow(unique(wildfire_dms[, .(disturbance_matrix_id)])), "unique wildfire DMs."))

The function returns a data.table in a “long” format, where each row represents a single transfer (proportion) from a source_pool to a sink_pool.

head(wildfire_dms)

Understanding the Output

A key concept is that the same fundamental disturbance matrix (identified by disturbance_matrix_id) can be applied to multiple regions (spatial units, which are Province x Ecozone combinations). This is why you might see what looks like duplicate information.

The id_title column provides a unique, human-readable identifier for each specific application of a DM (e.g., “Wildfire in Alberta’s Boreal Plains”).

Let’s look at a more specific query. Suppose we want to find all “Firewood” DMs in Alberta.

firewood_ab_dms <- get_disturbance_matrices(
  disturbance_type_group = "Firewood",
  provinces = "Alberta"
)

# How many unique titles vs. unique matrices?
unique_titles <- unique(firewood_ab_dms$id_title)
unique_matrices <- unique(firewood_ab_dms$disturbance_matrix_id)

message(paste("Found", length(unique_titles), "DM applications (id_title) across Alberta's ecozones."))
message(paste("These correspond to only", length(unique_matrices), "unique disturbance matrices (disturbance_matrix_id)."))

This shows that 3 unique firewood DMs are replicated across 7 different ecozones in Alberta, resulting in 21 unique combinations.

2. Visualizing Disturbance Matrices

Once you have a DM, the viz_disturbance_matrix() function can create an alluvial diagram to visualize the proportional carbon transfers. This is incredibly useful for understanding and verifying a disturbance’s impact.

Visualizing a Single DM

Let’s take one of the firewood DMs we just queried and plot it.

# Select the data for just one DM application
one_dm <- firewood_ab_dms[id_title == unique_titles[1]]

viz_disturbance_matrix(
  dm_data = one_dm,
  title = one_dm$id_title[1]
)

The plot shows carbon moving from source pools (left) to sink pools (right). The flows are colored by the decay rate of the sink pool, giving you a quick sense of the fate of the carbon. The function also validates that the proportions for each source pool sum to 1, warning you if there’s a mass balance issue.

Visualizing Multiple DMs

Comparing several DMs is easy using faceting. Let’s visualize the three unique firewood DMs from our previous query. We’ll use id_title to specify the column to facet by.

# We'll use the unique matrix name for faceting
three_dms <- firewood_ab_dms[id_title %in% unique_titles[c(4,11,18)]]

viz_disturbance_matrix(
  dm_data = three_dms,
  dm_id = "id_title",
  title = "Comparison of Firewood DMs in Alberta"
)

Customizing the Plot

The viz_disturbance_matrix() function offers several parameters for customization, such as ordering the facets, changing colors, and adjusting labels. This is great for creating publication-quality figures.

# Define a custom order for the facets
order_facets <- unique(three_dms[order(admin_boundary_name, disturbance_matrix_name)], by = "id_title")$id_title

viz_disturbance_matrix(
  dm_data = three_dms,
  dm_id = "id_title",
  title = "Comparison of Firewood DMs in Alberta (New Order and transparency)",
  order_dm_id = order_facets,
  flow_alpha = 0.6
)

You can explore all the options by looking at the documentation ?viz_disturbance_matrix.

3. Adding New Disturbance Matrices

rcbm4 also allows you to add your own custom DMs to a CBM database. This is essential for simulating novel disturbance types or severities.

The function for this is add_disturbance_matrices().

A very important note: This function modifies the CBM database directly. To avoid corrupting the default database included with the package, you should always work on a copy. The function has safeguards to warn you if you forget, but it’s best practice to be careful.

Let’s walk through the process of creating a new “Low Severity Wildfire” disturbance type.

Step 1: Create a Safe Workspace and a Database Copy

We’ll use a temporary directory for this example to keep things clean.

skip_if_no_libcbm()

# Create a temporary directory for our project
proj_path <- tempfile("dm_vignette")
dir.create(proj_path)

# Get the path to the original cbm_defaults.db. Don't modify this database only copies of it.
libcbm_resources <- reticulate::import("libcbm.resources")
cbm_defaults_path_original <- libcbm_resources$get_cbm_defaults_path()

# Define the path for our copy and create it
cbm_defaults_path_copy <- file.path(proj_path, "cbm_defaults_copy.db")
file.copy(from = cbm_defaults_path_original, to = cbm_defaults_path_copy)

message("Database copied to: ", cbm_defaults_path_copy)

Step 2: Create the New Disturbance Matrix Data

The easiest way to create new DM data is to start with an existing DM as a template. We’ll fetch a standard wildfire DM and modify its name and description.

The new_data argument requires a data.frame or data.table with specific columns: disturbance_matrix_name, disturbance_matrix_description, spatial_unit_id, source_pool_id, sink_pool_id, and proportion.

skip_if_no_libcbm()

# Get a template DM from our copied database
template_dm <- get_disturbance_matrices(
  cbm_defaults_path = cbm_defaults_path_copy,
  disturbance_matrix_names = "Wildfire for Newfoundland - Boreal Shield East"
)

# Keep only the required columns
new_dm_data <- template_dm[, .(
  disturbance_matrix_name,
  disturbance_matrix_description,
  spatial_unit_id,
  source_pool_id,
  sink_pool_id,
  proportion
)]

# Modify the name and description for our new DM
new_dm_data[, disturbance_matrix_name := "Low Severity Wildfire for NF-BS-E"]
new_dm_data[, disturbance_matrix_description := "A test low severity wildfire based on the default wildfire."]

# For a real new DM, you would now adjust the 'proportion' values.
# For this example, we will keep the original proportions.
# Remember: for each source pool, the sum of proportions must equal 1!

head(new_dm_data)

Step 3: Add the New DM to the Database

Now we call add_disturbance_matrices(), pointing to our copied database and providing the new data, along with a name and description for the new disturbance type we are creating.

skip_if_no_libcbm()

add_disturbance_matrices(
  cbm_defaults_path = cbm_defaults_path_copy,
  new_data = new_dm_data,
  disturbance_type_name = "Wildfire - Low Severity",
  disturbance_type_description = "A new disturbance type for low severity fires that cause less mortality."
)

Step 4: Verify the Addition

Let’s query our modified database to ensure the new DM is there.

skip_if_no_libcbm()

newly_added_dm <- get_disturbance_matrices(
  cbm_defaults_path = cbm_defaults_path_copy,
  disturbance_type_names = "Wildfire - Low Severity"
)

# Check the name of our new DM
unique(newly_added_dm$disturbance_matrix_name)

Success! Our new disturbance matrix is now in our custom database, ready to be used in CBM simulations.

Conclusion

In this guide, we’ve covered the essential workflow for managing disturbance matrices in rcbm4. You’ve learned how to query the database for existing DMs, visualize them to understand their function, and add your own custom DMs for advanced modeling scenarios. This powerful set of tools opens the door to tailoring CBM to your specific research questions. Happy modeling!