1- # ' @noRd
1+ # ' Compute predicted tree crown width using species-specific equations
2+ # '
3+ # ' `predict_crwidth()` computes tree crown width using species-specific
4+ # ' regression equations from the literature.
5+ # '
6+ # ' @details
7+ # ' Crown width is predicted from tree diameter using coefficients provided in
8+ # ' the lookup table [cw_coef] (see `?cw_coef` for detailed documentation and
9+ # ' references). The method also incorporates adjustment factors used to derive
10+ # ' crown width estimates for FIA "saplings", i.e., trees less than 5.0 in.
11+ # ' (12.7 cm) diameter but greater than or equal to 1.0 in. (2.54 cm) diameter.
12+ # ' Details are described in the documentation for the lookup table
13+ # ' [cw_sapling_adj].
14+ # '
15+ # ' Large diameter trees in the temperate rain forests of the Pacific Northwest
16+ # ' region can far exceed the range of diameters in the broadly applicable
17+ # ' datasets that have been used to develop crown width prediction equations. To
18+ # ' avoid extrapolation beyond the range of the model fitting data in those
19+ # ' cases, `predict_crwidth()` makes use of the "old growth" equation presented
20+ # ' by Gill et al. (2000) to estimate crown width for nine tree species when
21+ # ' their diameter is greater than 50 in. (127 cm).
22+ # '
23+ # ' @param tree_list A data frame containing tree records. Must have columns
24+ # ' `SPCD` (FIA integer species code), `STATUSCD` (FIA integer tree status code,
25+ # ' 1 = live) and `DIA` (FIA tree diameter in inches).
26+ # ' @param digits Optional integer indicating the number of digits to keep in the
27+ # ' return values (defaults to `1`).
28+ # ' @return
29+ # ' A numeric vector of length `nrow(tree_list)` with predicted crown width in
30+ # ' feet for live trees. `NA` is returned for trees with `STATUSCD != 1`.
31+ # '
32+ # ' @references
33+ # ' Gill, S.J., G.S. Biging, E.C. Murphy. 2000. Modeling conifer tree crown
34+ # ' radius and estimating canopy cover. _Forest Ecology and Management_, 126(3):
35+ # ' 405-416.
36+ # '
37+ # ' @examples
38+ # ' predict_crwidth(plantation)
239# ' @export
3- predict_crwidth <- function (tree_list ) {
40+ predict_crwidth <- function (tree_list , digits = 1 ) {
441 if (missing(tree_list ) || is.null(tree_list ))
542 stop(" 'tree_list' is required" , call. = FALSE )
643
@@ -26,12 +63,15 @@ predict_crwidth <- function(tree_list) {
2663 if (any(is.na(tree_list $ DIA )))
2764 stop(" 'tree_list$DIA' cannot have missing values" , call. = FALSE )
2865
29- # default regression coefficients if species-specific ones are missing
30- # SPCD == 807, blue oak
31- b_default <- cw_coef [cw_coef $ SPCD == 807 , c(" b0" , " b1" , " b2" )]
66+ if (is.null(digits ))
67+ digits <- 2
3268
3369 cw <- rep_len(NA_real_ , nrow(tree_list ))
3470
71+ # define a default equation to use in case a species-specific one is missing
72+ # SPCD == 807, blue oak
73+ b_default <- cw_coef [cw_coef $ SPCD == 807 , c(" b0" , " b1" , " b2" )]
74+
3575 # special case for large trees of certain species in the PNW region:
3676 # use the "old growth" equation from Gill et al. (2000)
3777 old_growth_trees <- tree_list $ DIA > 50 & tree_list $ STATUSCD == 1 &
@@ -47,24 +87,39 @@ predict_crwidth <- function(tree_list) {
4787 if (nrow(b ) == 0 )
4888 b <- b_default
4989
50- this_subset <- tree_list $ SPCD == spcd & tree_list $ STATUSCD == 1 &
51- is.na(cw )
90+ this_subset <-
91+ tree_list $ SPCD == spcd & tree_list $ STATUSCD == 1 & is.na(cw )
5292
53- if (length(this_subset ) > 0 ) {
54- cw [this_subset ] <- b $ b0 [1 ] +
55- b $ b1 [1 ] * pmax(5 , tree_list $ DIA [this_subset ]) +
56- b $ b2 [1 ] * pmax(5 , tree_list $ DIA [this_subset ])^ 2
57- }
93+ cw [this_subset ] <-
94+ b $ b0 + b $ b1 * pmax(5 , tree_list $ DIA [this_subset ]) +
95+ b $ b2 * pmax(5 , tree_list $ DIA [this_subset ])^ 2
5896 }
5997
6098 # apply sapling crown width adjustment factors
6199 saplings <- tree_list $ DIA < 5 & tree_list $ STATUSCD == 1
62100 sapling_spp <- unique(tree_list $ SPCD [saplings ])
63- # species-specific adjustment factors if any
64- spp_adj <- intersect(sapling_spp , cw_sapling_adj $ SPCD )
65- # TODO:
66- # ...
67-
101+ # species-specific adjustment factors if any (based on Bragg 2001)
102+ spcd_adj <- intersect(sapling_spp , cw_sapling_adj $ SPCD )
103+ for (spcd in spcd_adj ) {
104+ rowid <- which(cw_sapling_adj $ SPCD == spcd )
105+ # adjustment factors at 1, 2, 3, 4, 5 inches DIA:
106+ adj_factors <- c(as.numeric(cw_sapling_adj [rowid , 2 : 5 ]), 1 )
107+ this_subset <- saplings & tree_list $ SPCD == spcd
108+ # interpolated adjustment factors for the actual sapling diameters:
109+ n <- trunc(tree_list $ DIA [this_subset ])
110+ cw_adj <- (tree_list $ DIA [this_subset ] - n ) *
111+ (adj_factors [n + 1 ] - adj_factors [n ]) + adj_factors [n ]
112+ cw [this_subset ] <- cw [this_subset ] * cw_adj
113+ }
114+ # otherwise use avarage adjustment factors based on Bragg (2001) data
115+ # average adjustment factors at 1, 2, 3, 4, 5 inches DIA:
116+ adj_factors <- c(0.509 , 0.644 , 0.767 , 0.885 , 1.0 )
117+ this_subset <- saplings & ! (tree_list $ SPCD %in% cw_sapling_adj $ SPCD )
118+ # interpolated adjustment factors for the actual sapling diameters:
119+ n <- trunc(tree_list $ DIA [this_subset ])
120+ cw_adj <- (tree_list $ DIA [this_subset ] - n ) *
121+ (adj_factors [n + 1 ] - adj_factors [n ]) + adj_factors [n ]
122+ cw [this_subset ] <- cw [this_subset ] * cw_adj
68123
69- return (cw )
124+ round (cw , digits = digits )
70125}
0 commit comments