Title: | Correction Factors for Tree Plot Areas Intersected by Stand Boundaries |
---|---|
Description: | The German national forest inventory uses angle count sampling, a sampling method first published as `Bitterlich, W.: Die Winkelzählmessung. Allgemeine Forst- und Holzwirtschaftliche Zeitung, 58. Jahrg., Folge 11/12 vom Juni 1947` and extended by Grosenbaugh (<https://academic.oup.com/jof/article-abstract/50/1/32/4684174>) as probability proportional to size sampling. When plots are located near stand boundaries, their sizes and hence their probabilities need to be corrected. |
Authors: | Andreas Dominik Cullmann [aut, cre], Bernhard Bösch [ctb], Christoph Fischer [ctb], Gerald Kändler [ctb] |
Maintainer: | Andreas Dominik Cullmann <[email protected]> |
License: | BSD_2_clause + file LICENSE |
Version: | 2.1.0.9000 |
Built: | 2025-01-26 03:56:14 UTC |
Source: | https://gitlab.com/fvafrcu/treeplotarea |
The German national forest inventory uses angle count sampling, a sampling method first published by Bitterlich (1947) and extended by Grosenbaugh (1952) as probability proportional to size sampling. When plots are located near stand boundaries, their sizes and hence their probabilities need to be corrected.
You will find the details invignette("An_Introduction_to_treePlotArea", package =
"treePlotArea")
.
Maintainer: Andreas Dominik Cullmann [email protected]
Other contributors:
Bernhard Bösch [contributor]
Christoph Fischer [contributor]
Gerald Kändler [contributor]
Bitterlich, W. (1947): Die Winkelzählmessung. Allgemeine Forst- und Holzwirtschaftliche Zeitung, 58.
Grosenbaugh, L. R. (1952): Plotless Timber Estimates – New, Fast, Easy. Journal of Forestry. https://academic.oup.com/jof/article-abstract/50/1/32/4684174.
Useful links:
An extract from the the federal database. Refer to Aufnahmeanweisung für die vierte Bundeswaldinventur (2021 - 2022).
data("boundaries", package = "treePlotArea")
data("boundaries", package = "treePlotArea")
A data frame with 148 observations on the following 13 variables. Variables not needed with the package are marked with an asterisk.
tnr
The tract id.
enr
The corner id. A tract may have up to 4 corners on wooden floor.
vbl
* An indicator giving the country. 804 denotes Baden-Wuerttemberg.
rnr
* The boundary id.
rk
An indicator giving the validity of the boundary. Values of 9 or higher indicate that this boundary is not valid (any more).
rart
An indicator giving the type of the boundary (stand or forest boundary, for example).
rterrain
* An Indicator giving the type of terrain behind the border.
spa_gon
The azimuth in gon of the starting point of the boundary.
spa_m
The distance to the starting point of the boundary in centimeter
spk_gon
As above, for the boundary's flexing point.
spk_m
As above, for the boundary's flexing point.
spe_gon
As above, for the boundary's stopping point.
spe_m
As above, for the boundary's stopping point.
Aufnahmeanweisung für die vierte Bundeswaldinventur (2021 - 2022) Johann Heinrich von Thünen-Institut. Bundesforschungseinheit für Ländliche Räume, Wald und Fischerei, Thünen-Institut für Waldökologie.
boundaries <- get(data("boundaries", package = "treePlotArea"))
boundaries <- get(data("boundaries", package = "treePlotArea"))
The data tree coming with this package was processed by Gerald Kaendler for the country of Baden-Wuerttemberg, and is the reference for testing as he adjusted diameter measurements to breast height where they had been measured in diverging heights (due to deformations of trees at breast height). Which we really need to do. But he did some other things we need to revert if we want to follow the standards from the federal database. He
converted the diameter at breast height from millimeter to centimeter and renamed it,
converted horizontal distance from centimeter to meter and renamed it.
So we add two variables holding the diameter in millimeter and the horizontal
distance in centimeter, named by the output of getOption("treePlotArea")[["angle_counts"]][["dbh"]]
andgetOption("treePlotArea")[["angle_counts"]][["distance"]]
respectively.
bw2bwi2022de(x)
bw2bwi2022de(x)
x |
A tree data set, typically
|
A tree data set prepared to work with the package.
Other data functions:
select_valid_angle_count_trees()
trees <- get(data("trees", package = "treePlotArea")) summary(trees) angle_counts <- bw2bwi2022de(trees) summary(angle_counts)
trees <- get(data("trees", package = "treePlotArea")) summary(trees) angle_counts <- bw2bwi2022de(trees) summary(angle_counts)
There is a boundary (tract 6878, corner 1, boundary 1) in the federal database for the 2012 survey that runs exactly through the plot. If that boundary would be valid, at that corner the term "stand" is not defined.
check_boundaries(x, stop_on_error = TRUE, clean_data = FALSE)
check_boundaries(x, stop_on_error = TRUE, clean_data = FALSE)
x |
A |
stop_on_error |
Throw an error if invalid boundaries are found? |
clean_data |
Get rid of invalid boundaries? |
So we check for such boundaries. These are straight boundaries with identical azimuth values for start and end, and flexed boundaries where azimuth values for either start or end and the azimuth value for the nook are identical and the nook is farther away form the plot than the corresponding start or end.
A (possibly cleansed) data.frame
containing boundaries.
Other boundary functions:
get_boundary_polygons()
data("boundaries", package = "treePlotArea") validate_data(x = boundaries) check_boundaries(boundaries)
data("boundaries", package = "treePlotArea") validate_data(x = boundaries) check_boundaries(boundaries)
Used by get_correction_factors
to convert a boundary table
to polygons. You may want to see the polygons, that is why we exported this
function.
get_boundary_polygons(boundaries, stop_on_error = TRUE, clean_data = FALSE)
get_boundary_polygons(boundaries, stop_on_error = TRUE, clean_data = FALSE)
boundaries |
A |
stop_on_error |
Throw an error if invalid boundaries are encountered? (There was tract 6878, corner 1, boundary 1 in the federal database for the 2012 survey, runs through the plot. There is no stand defined that way!). |
clean_data |
Omit invalid boundaries in any further calculations? |
A list with all boundary polygons for each corner for each tract.
Other boundary functions:
check_boundaries()
boundaries <- get(data("boundaries", package = "treePlotArea")) boundary_polygons <- get_boundary_polygons(boundaries)
boundaries <- get(data("boundaries", package = "treePlotArea")) boundary_polygons <- get_boundary_polygons(boundaries)
Get correction factors for an angle count table (i.e. a
data.frame
) and a corresponding boundary
table (i.e. a data.frame
).
get_correction_factors( angle_counts, boundaries, verbose = TRUE, stop_on_error = FALSE, skip_check = FALSE, counting_factor = 4, is_ti_round = TRUE )
get_correction_factors( angle_counts, boundaries, verbose = TRUE, stop_on_error = FALSE, skip_check = FALSE, counting_factor = 4, is_ti_round = TRUE )
angle_counts |
A |
boundaries |
A |
verbose |
Be verbose? |
stop_on_error |
Passed to |
skip_check |
We usually check if the angle counts are suitable (for example whether a diameter at breast height, a horizontal distance and an azimuth measurement are given). Skip this check? This might be of interest if you want to check whether another plot with no dbh recorded (for example a corner) is intersected by a boundary. |
counting_factor |
The basal area factor used in counting the trees. For tally trees in the German national forest inventory its value is 4 [m^2]. |
is_ti_round |
When checking for the boundary circle of a tree to include the center of the plot: round that circle's radius to the unit (i.e. [cm]) as done by Thuenen Institute? |
The columns in the names have to be named according to the values of
getOption("treePlotArea")
.
If they do not: you can either rename the columns
or set the option accordingly, probably using set_options
.
A data.frame
containing the correction factors and a
status giving information on possibly errors.
set_options
data("trees", "boundaries", package = "treePlotArea") # For CRAN's sake: draw a subset tracts <- c(sample(boundaries[["tnr"]], 20), 10056) # Calculate correction factors trees <- subset(trees, tnr %in% tracts) boundaries <- subset(boundaries, tnr %in% tracts) angle_counts <- bw2bwi2022de(trees) validate_data(x = boundaries) validate_data(x = angle_counts) boundary_polygons <- get_boundary_polygons(boundaries) correction_factors <- get_correction_factors(angle_counts, boundary_polygons) summary(correction_factors$status) # Select valid angle count trees only valid_angle_counts <- select_valid_angle_count_trees(angle_counts) correction_factors <- get_correction_factors(valid_angle_counts, boundary_polygons) summary(correction_factors$status) # Select a single tree tnr <- 10056 enr <- 4 bnr <- 3 tree <- valid_angle_counts[valid_angle_counts[["tnr"]] == tnr & valid_angle_counts[["enr"]] == enr & valid_angle_counts[["bnr"]] == bnr, TRUE] bounds <- boundaries[boundaries[["tnr"]] == tnr & boundaries[["enr"]] == enr, TRUE] get_correction_factors(tree, bounds) # Deadwood plots: dead_wood_plots <- unique(trees[TRUE, c("tnr", "enr")]) dead_wood_plots[["bnr"]] <- 0 dead_wood_plots[["hori"]] <- 0 dead_wood_plots[["azi"]] <- 0 dead_wood_plots[["bhd"]] <- 200 get_correction_factors(dead_wood_plots, boundary_polygons, skip_check = TRUE) # Set the deadwood plot's radius to 500 mm dead_wood_plots[["bhd"]] <- 5000 # The counting factor has unit square meters per area. # Area is hardcoded to 10000 [square meters], so to get a plot radius that's # equal to the dbh, we need 2 * sqrt(counting_factor) / sqrt(10000) to be # equal to 1. get_correction_factors(dead_wood_plots, boundary_polygons, skip_check = TRUE, counting_factor = 2500)
data("trees", "boundaries", package = "treePlotArea") # For CRAN's sake: draw a subset tracts <- c(sample(boundaries[["tnr"]], 20), 10056) # Calculate correction factors trees <- subset(trees, tnr %in% tracts) boundaries <- subset(boundaries, tnr %in% tracts) angle_counts <- bw2bwi2022de(trees) validate_data(x = boundaries) validate_data(x = angle_counts) boundary_polygons <- get_boundary_polygons(boundaries) correction_factors <- get_correction_factors(angle_counts, boundary_polygons) summary(correction_factors$status) # Select valid angle count trees only valid_angle_counts <- select_valid_angle_count_trees(angle_counts) correction_factors <- get_correction_factors(valid_angle_counts, boundary_polygons) summary(correction_factors$status) # Select a single tree tnr <- 10056 enr <- 4 bnr <- 3 tree <- valid_angle_counts[valid_angle_counts[["tnr"]] == tnr & valid_angle_counts[["enr"]] == enr & valid_angle_counts[["bnr"]] == bnr, TRUE] bounds <- boundaries[boundaries[["tnr"]] == tnr & boundaries[["enr"]] == enr, TRUE] get_correction_factors(tree, bounds) # Deadwood plots: dead_wood_plots <- unique(trees[TRUE, c("tnr", "enr")]) dead_wood_plots[["bnr"]] <- 0 dead_wood_plots[["hori"]] <- 0 dead_wood_plots[["azi"]] <- 0 dead_wood_plots[["bhd"]] <- 200 get_correction_factors(dead_wood_plots, boundary_polygons, skip_check = TRUE) # Set the deadwood plot's radius to 500 mm dead_wood_plots[["bhd"]] <- 5000 # The counting factor has unit square meters per area. # Area is hardcoded to 10000 [square meters], so to get a plot radius that's # equal to the dbh, we need 2 * sqrt(counting_factor) / sqrt(10000) to be # equal to 1. get_correction_factors(dead_wood_plots, boundary_polygons, skip_check = TRUE, counting_factor = 2500)
Used to see (not set) the default options set by treePlotArea.
Use set_options
to change these default values.
get_defaults()
get_defaults()
A named list. It has the following entries giving the column names of the angle count or boundary data that hold information on:
The tract id.
The corner id.
The tree id.
The distance from the center of the tract's corner.
The azimuth from North.
The diameter at breast height.
The tract id.
The corner id.
Type of boundary.
Validity of the boundary.
The starting point's distance.
The flexing point's distance.
The ending point's distance.
The starting point's azimuth.
The flexing point's azimuth.
The ending point's azimuth.
Other option functions:
set_options()
get_defaults()
get_defaults()
Visualize a corner, its boundaries and tree plot areas.
plot_tree_plot_area( angle_counts, boundaries, tnr, enr, bnr = NULL, frame_factor = 1, use_sub = NULL )
plot_tree_plot_area( angle_counts, boundaries, tnr, enr, bnr = NULL, frame_factor = 1, use_sub = NULL )
angle_counts |
A |
boundaries |
A |
tnr |
Number of the tract. |
enr |
Number of the tract's corner. |
bnr |
If given, the number of a corner's tree. |
frame_factor |
Plotting from as a factor of the tree plot area. Stick with the default. |
use_sub |
Deprecated. |
The corrections factors for the trees' plot areas.
tnr <- 166 enr <- 2 bnr <- 7 angle_counts <- bw2bwi2022de(get(data("trees", package = "treePlotArea"))) plot_tree_plot_area(angle_counts = angle_counts, boundaries = get(data("boundaries", package = "treePlotArea")), tnr = tnr, enr = enr, bnr = bnr, frame_factor = 4) plot_tree_plot_area(angle_counts = angle_counts, boundaries = get(data("boundaries", package = "treePlotArea")), tnr = tnr, enr = enr, frame_factor = 1)
tnr <- 166 enr <- 2 bnr <- 7 angle_counts <- bw2bwi2022de(get(data("trees", package = "treePlotArea"))) plot_tree_plot_area(angle_counts = angle_counts, boundaries = get(data("boundaries", package = "treePlotArea")), tnr = tnr, enr = enr, bnr = bnr, frame_factor = 4) plot_tree_plot_area(angle_counts = angle_counts, boundaries = get(data("boundaries", package = "treePlotArea")), tnr = tnr, enr = enr, frame_factor = 1)
The tree data coming with this package was processed by Gerald Kaendler for
the
country of Baden-Wuerttemberg, and is the reference for testing as he
adjusted diameter measurements to breast height where they had been measured
in diverging heights (due to deformations of trees at breast height).
Which we really need to do.
But he also
added trees that are not part of the angle count sampling, which this
function removes. We need that mainly to run tests against the reference
values computed by grenzkreis
because we would not be able to
easily find the keys to merge the data. So this function is probably of
no use to you.
And we remove trees with a diameter at breast height greater than zero and a
distance of 0, for these tree should not be there.
select_valid_angle_count_trees(x, sample_type = "stp", tree_status = "pk")
select_valid_angle_count_trees(x, sample_type = "stp", tree_status = "pk")
x |
A tree data set, typically
|
sample_type |
An indicator giving the type of sample the tree was in. 0 marks the angle count sample with counting factor 4. |
tree_status |
An indicator giving the status of a tree in the German national forest inventory. 0 marks ingrowth, 1 marks ongrowth. |
A tree data containing valid angle count trees only.
Other data functions:
bw2bwi2022de()
trees <- get(data("trees", package = "treePlotArea")) subset(trees, entf == 0 & bhd2 > 0 & stp == 0) angle_counts <- select_valid_angle_count_trees(trees) subset(angle_counts, entf == 0 & bhd2 > 0 & stp == 0)
trees <- get(data("trees", package = "treePlotArea")) subset(trees, entf == 0 & bhd2 > 0 & stp == 0) angle_counts <- select_valid_angle_count_trees(trees) subset(angle_counts, entf == 0 & bhd2 > 0 & stp == 0)
Just convenience function for options
.
treePlotArea has a set of default options to define the columns of the
data.frames
that are passed to
get_correction_factors
.
See get_defaults
for a description of these options.
set_options(...)
set_options(...)
... |
See |
Other option functions:
get_defaults()
# Set the default set_options() getOption("treePlotArea") # Overwrite some option_list <- list(angle_counts = list(dbh = "diameter"), boundaries = list(boundary_status = "boundart_stat")) set_options(angle_counts = option_list[["angle_counts"]], boundaries = option_list[["boundaries"]]) getOption("treePlotArea")$angle_counts$dbh # restore default option_list <- get_defaults() set_options(angle_counts = option_list[["angle_counts"]], boundaries = option_list[["boundaries"]]) getOption("treePlotArea")$angle_counts$dbh
# Set the default set_options() getOption("treePlotArea") # Overwrite some option_list <- list(angle_counts = list(dbh = "diameter"), boundaries = list(boundary_status = "boundart_stat")) set_options(angle_counts = option_list[["angle_counts"]], boundaries = option_list[["boundaries"]]) getOption("treePlotArea")$angle_counts$dbh # restore default option_list <- get_defaults() set_options(angle_counts = option_list[["angle_counts"]], boundaries = option_list[["boundaries"]]) getOption("treePlotArea")$angle_counts$dbh
This is an extract form a data set prepared by Gerald Kaendler. He
added trees that are not part of the angle count sampling,
converted the diameter at breast height from millimeter to centimeter and renamed it,
converted horizontal distance from centimeter to meter and renamed it,
computed correction factors using grenzkreis
.
data("trees", package = "treePlotArea")
data("trees", package = "treePlotArea")
A data frame with 1121 observations on the following 9 variables. Variables not needed with the package are marked with an asterisk.
tnr
The tract id.
enr
The corner id. A tract may have up to 4 corners on wooden floor.
bnr
The tree id.
bhd2
The diameter at breast height, given in centimeter
.
kf2
* The correction factor given by grenzkreis
.
entf
The trees' distance from the center of the tract's corner, given in meter.
azi
The azimuth from North, measured in gon (or gradian).
pk
* An indicator giving the type of a tree in the German national forest inventory. 0 marks ingrowth, 1 marks ongrowth.
stp
* An indicator giving the type of sample the tree was in. 0 marks the angle count sample with counting factor 4.
trees <- get(data("trees", package = "treePlotArea")) summary(trees) angle_counts <- bw2bwi2022de(trees) summary(angle_counts)
trees <- get(data("trees", package = "treePlotArea")) summary(trees) angle_counts <- bw2bwi2022de(trees) summary(angle_counts)
The 2012 data of the federal database contains tract 18063, corner 2.
There are boundaries recorded for that corner, nevertheless tree 14 has no
azimuth measurement. This function therefore checks for the data sets not
having missing
data in the columns needed by get_correction_factors
and
optionally removes affected observations.
It does not cross check whether missing data is really needed (azimuth is
not when there is no boundary recorded for that tracts corner).
validate_data(x, type = c(NA, "angle_counts", "boundaries"), clean = FALSE)
validate_data(x, type = c(NA, "angle_counts", "boundaries"), clean = FALSE)
x |
A tree or angle count data set. |
type |
The type of data, stick with the default to let us guess. |
clean |
Omit missing data? If the input contains missing data in the
columns needed by |
A tree data set. The input, if that was valid data, the cleaned input otherwise. Throws an error if columns are missing.
boundaries <- get(data("boundaries", package = "treePlotArea")) nrow(boundaries) nrow(validate_data(x = boundaries)) boundaries[1, "enr"] <- NA try(validate_data(boundaries)) nrow(validate_data(boundaries, clean = TRUE))
boundaries <- get(data("boundaries", package = "treePlotArea")) nrow(boundaries) nrow(validate_data(x = boundaries)) boundaries[1, "enr"] <- NA try(validate_data(boundaries)) nrow(validate_data(boundaries, clean = TRUE))