Everything in this document can be rebuilt from the files in its project folder. This appendix lists them: the data, the scripts that made the data, the functions the chapters define, and the software they run on. Chapter 10 argued that a map made from points and rules is worth keeping because it can be rebuilt. This is the same idea applied to the document itself.
Show the code
## --- Standard packages ---## many useful functions, including read_csv()library(tidyverse)## formatted tableslibrary(gt)## --- Options and defaults ---## suppress read_csv() column-type messagesoptions(readr.show_col_types =FALSE)
Data files
All the data files are in the data folder. Most are small, so any chapter can be run on its own.
Show the code
## the list of data files, with their sourcesdata_files <-read_csv("data/appendix_data_files.csv")## add the size of each file, in kilobytesdata_files <-mutate(data_files, kb =round(file.size(file.path("data", file)) /1024))## show itdata_files |>select(file, contents, source, kb, made_by, chapters) |>gt() |>cols_label(file ="File", contents ="Contents", source ="Source", kb ="Size (KB)",made_by ="Made by", chapters ="Chapters") |>tab_style(style =cell_text(font ="monospace", size ="small"), locations =cells_body(columns =c(file, made_by)))
File
Contents
Source
Size (KB)
Made by
Chapters
kipuka_puaulu_releves.csv
12 demonstration points: ID, UTM easting and northing, vegetation type
Points placed 3 per canopy structure class; types read from Mueller-Dombois and Fosberg (1974)
1
prototype/canopy_voronoi_prototype_v1.R
2-9
kipuka_puaulu_study_area.csv
Corners of the 3.2 by 2.6 km study-area rectangle (UTM zone 5N)
Centered on photographs taken in the kīpuka
0
prototype/canopy_voronoi_prototype_v1.R
2-10
kipuka_puaulu_outline.geojson
Outline of Kīpuka Puaulu (94.5 ha)
Traced from canopy height over 8 m
293
Chapter 8 (the tracing code)
3, 6, 8, 9
kipuka_puaulu_specimens.csv
164 herbarium specimens with species, family, status, year, herbarium and coordinates
GBIF preserved specimens within 2 km of the kīpuka, accessed 2026-07-05, one sheet per gathering
14
the checklists project (Projects/checklists)
6
kipuka_puaulu_canopy_height.tif
Canopy height in 5 m cells for the study area
Meta and World Resources Institute global 1 m canopy height map (Tolan et al. 2024)
322
R/make_kipuka_canopy_data.R
8-9
mdf1974_classes.tif
The 1974 vegetation map as classes in 5 m cells
Mueller-Dombois and Fosberg (1974), sheets 12 and 13, digitized
9
R/make_mdf1974_data.R
9
mdf1974_classes.csv
Names of the 1974 classes
Mueller-Dombois and Fosberg (1974)
0
R/make_mdf1974_data.R
9
la_gardens.csv
Five Los Angeles basin botanical gardens: city, area, location, Wikipedia article and 2024 pageviews
Wikipedia; OpenStreetMap (Nominatim); Wikimedia pageviews API
1
R/make_la_gardens_data.R
7
la_land_frame.geojson
Land frame for the Los Angeles basin
U.S. Census Bureau county boundaries, 2020 (via tigris)
14
R/make_la_gardens_data.R
7
la_tracts_2020.csv
3,207 census tracts: ID, 2020 population, a point inside each tract
U.S. Census Bureau, 2020 Census (P1_001N, via tidycensus)
115
R/make_la_gardens_data.R
7
Scripts that make the data
Three of the data files come from scripts in the R folder. Each one runs once, from the project folder, and writes its files into data. The chapters read the files; they don’t run the scripts.
Show the code
## the scripts, what they make, and what they needscripts <-read_csv(file ="script,makes,needsR/make_kipuka_canopy_data.R,kipuka_puaulu_canopy_height.tif,an internet connection (no key)R/make_mdf1974_data.R,mdf1974_classes.tif and mdf1974_classes.csv,the digitized map sheets in expert_map/ and the canopy file (for its grid)R/make_la_gardens_data.R,la_gardens.csv; la_land_frame.geojson; la_tracts_2020.csv,an internet connection and a Census API keyR/fig_ch1_voronoi.R,the Voronoi map in Chapter 1,the points and study area files")## show itscripts |>gt() |>cols_label(script ="Script", makes ="Makes", needs ="Needs") |>tab_style(style =cell_text(font ="monospace", size ="small"), locations =cells_body(columns = script))
Script
Makes
Needs
R/make_kipuka_canopy_data.R
kipuka_puaulu_canopy_height.tif
an internet connection (no key)
R/make_mdf1974_data.R
mdf1974_classes.tif and mdf1974_classes.csv
the digitized map sheets in expert_map/ and the canopy file (for its grid)
Each chapter defines the functions it needs, so that each chapter runs on its own. That means some functions appear in more than one chapter. The table gathers them in the order the document uses them. The tessellr package, in the next section, gathers the same ideas in general form.
Show the code
## the functions defined in the chaptersfunctions <-read_csv("data/appendix_functions.csv")## show them, grouped by stagefunctions |>gt(groupname_col ="stage") |>cols_label(fun ="Function", arguments ="Arguments", purpose ="Purpose", chapters ="Chapters") |>tab_style(style =cell_text(font ="monospace", size ="small"), locations =cells_body(columns =c(fun, arguments))) |>tab_style(style =cell_text(weight ="bold"), locations =cells_row_groups())
Function
Arguments
Purpose
Chapters
Building tiles
make_tiles
points, frame
Build Voronoi tiles around the points, trim them to the frame, and attach each point's attributes to its tile
3-6
Reading tiles
pattern_tiles
pts, label
Build tiles for one point pattern and flag the interior tiles
5
cv_of
tiles
Coefficient of variation of interior tile area
5
pattern_map
tiles, title
Map one pattern, shaded by tile area
5
Tiles as containers
count_tiles
tiles, points
Count the points (such as specimens) that fall in each tile
6
Weighted tiles
winning_garden
xy, weights
For each location, the garden with the smallest distance divided by weight
7
service_map
weights
Service areas on a 500 m grid of land cells
7
people_won
weights
People living in each garden's service area, from census tracts
7
draw_service
areas, title
Draw one service-area map
7
Adding the canopy
nearest_type
px, py, type, point_class, constrained
Plain or structure-constrained Voronoi on a raster grid
8-9
map_polys, type_polys
a raster of types
Turn a raster of vegetation types into polygons for drawing
8-9
draw_veg, draw_with_lines
a raster of types, title
Draw a vegetation map, with or without the 1974 lines
8-9
Checking the map
area_agree
v
Share of the area with the same type as the 1974 map
9
edges_of
v
Boundary cells of a map
9
boundary_agree
v
Share of the 1974 boundary within 50 m of the map's boundary, the reverse, and the length drawn
9
The tessellr package
The code in the chapters is written to teach. Each chapter repeats what it needs, and some of it is specific to Kīpuka Puaulu. The companion R package, tessellr, gathers the same ideas in general form, for any points and any area. Its canopy function reads the Meta and World Resources Institute map for any frame, not only the one tile that covers the kīpuka, and its counting function adds Poisson tests and a choice of how to handle uncertain locations. The package’s tests reproduce the numbers in Chapters 3 to 9.
Install it from GitHub:
## install the companion packageremotes::install_github("kimbridges/tessellr")
Its functions, in the same five groups as the chapters:
Show the code
## the functions in tessellr, with their arguments and defaultstessellr_functions <-read_csv("data/appendix_tessellr.csv")## show them, grouped by stagetessellr_functions |>select(stage, usage, purpose) |>gt(groupname_col ="stage") |>cols_label(usage ="Function", purpose ="Purpose") |>tab_style(style =cell_text(font ="monospace", size ="small"), locations =cells_body(columns = usage)) |>tab_style(style =cell_text(weight ="bold"), locations =cells_row_groups()) |>tab_source_note(source_note ="Each function has a help page with a worked example; see ?tile_points and so on once the package is loaded.")
Plain or structure-constrained Voronoi map on a grid
Checking
map_agreement(map, reference, tolerance = 50)
Agreement between a map and a reference map
Data
kipuka_frame()
The Kīpuka Puaulu study area
kipuka_releves
Twelve demonstration points at Kīpuka Puaulu
Each function has a help page with a worked example; see ?tile_points and so on once the package is loaded.
The two functions at the heart of the method
Two functions carry the main ideas. The first builds a plain Voronoi map from points, in three steps. It’s the one Chapters 3 to 6 use.
## a function for the three tile-building steps from Chapter 2make_tiles <-function(points, frame) {## build the tiles around all the points tiles_all <-st_voronoi(st_union(points), envelope = frame)## split the result into separate polygons tiles <-st_collection_extract(tiles_all)## trim the tiles to the frame tiles <-st_intersection(tiles, frame)## attach each tile to the point inside it tiles <-st_sf(geometry = tiles)st_join(tiles, points)}
The second works on a grid of cells instead of polygons. With constrained = FALSE it gives the same map as make_tiles(), drawn in cells. With constrained = TRUE it applies the rule from Chapter 8: each cell takes the type of the nearest point in the same structure class. It expects two objects to exist already: cell_xy, the coordinates of the cell centers, and cell_class, the structure class of each cell.
## a function that assigns every cell to its nearest point, with or without the structure rulenearest_type <-function(px, py, type, point_class, constrained) { best <-rep(Inf, nrow(cell_xy)) out <-rep(NA_integer_, nrow(cell_xy))for (i inseq_along(px)) {## squared distance from every cell to point i d <- ((cell_xy[, 1] - px[i])^2) + ((cell_xy[, 2] - py[i])^2)## under the structure rule, points in other classes are out of reachif (constrained) d[cell_class != point_class[i]] <-Inf## keep point i wherever it's nearer than anything found so far closer <- d < best best[closer] <- d[closer] out[closer] <- type[i] } out}
## the packages used in the chapters and the data scriptspackages <-c("tidyverse", "gt", "patchwork", "ggrepel", "sf", "terra", "tidycensus", "tigris", "jsonlite", "tessellr")## their versions, with R itself at the topsoftware <-tibble(software =c("R", "Quarto", packages),version =c(as.character(getRversion()),as.character(quarto::quarto_version()),sapply(packages, function(p) tryCatch(as.character(packageVersion(p)), error =function(e) "not installed"))))## show itsoftware |>gt() |>cols_label(software ="Software", version ="Version")
R Core Team. 2024. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Walker, Kyle, and Matt Herman. 2025. Tidycensus: Load US Census Boundary and Attribute Data as ’Tidyverse’ and ’Sf’-Ready Data Frames. https://CRAN.R-project.org/package=tidycensus.