├── .Rbuildignore ├── .github ├── .gitignore ├── CONTRIBUTING.md ├── issue_template.md ├── pull_request_template.md └── workflows │ ├── R-CMD-check.yaml │ ├── pr-commands.yaml │ └── test-coverage.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── allodb-package.R ├── data.R ├── est_params.R ├── get_biomass.R ├── illustrate_allodb.R ├── imports.R ├── new_equations.R ├── resample_agb.R ├── sysdata.rda ├── validate_equation.R └── weight_allom.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── allodb.Rproj ├── codecov.yml ├── cran-comments.md ├── data-raw ├── available_random_ids.csv ├── available_random_ids.md ├── climatezones.R ├── csv_database │ ├── equations.csv │ ├── equations_metadata.csv │ ├── missing_values.csv │ ├── references.csv │ ├── references_metadata.csv │ ├── sites_info.csv │ ├── sitespecies.csv │ └── sitespecies_metadata.csv ├── data.R ├── shrub_species.R └── shrub_species.rds ├── data ├── equations.rda ├── equations_metadata.rda ├── genus_family.rda ├── gymno_genus.rda ├── koppenMatrix.rda ├── missing_values.rda ├── references.rda ├── references_metadata.rda ├── scbi_stem1.rda ├── shrub_species.rda ├── sites_info.rda ├── sitespecies.rda └── sitespecies_metadata.rda ├── inst └── WORDLIST ├── man ├── allodb-package.Rd ├── equations.Rd ├── est_params.Rd ├── figures │ ├── README-est-params-acer-1.png │ └── README-resample-acer-1.png ├── genus_family.Rd ├── get_biomass.Rd ├── gymno_genus.Rd ├── illustrate_allodb.Rd ├── koppenMatrix.Rd ├── missing_values.Rd ├── new_equations.Rd ├── references.Rd ├── resample_agb.Rd ├── scbi_stem1.Rd ├── shrub_species.Rd ├── sites_info.Rd ├── sitespecies.Rd └── weight_allom.Rd ├── tests ├── testthat.R └── testthat │ ├── _snaps │ ├── FIXME.md │ └── new_equations.md │ ├── test-FIXME.R │ ├── test-data.R │ ├── test-equations.R │ ├── test-est_params.R │ ├── test-get_biomass.R │ ├── test-illustrate_allodb.R │ ├── test-new_equations.R │ ├── test-resample_agb.R │ ├── test-validate_equation.R │ └── test-weight_allom.R └── vignettes ├── .gitignore └── allodb.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^\.buildignore$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^data-raw$ 5 | ^_pkgdown\.yml$ 6 | ^LICENSE\.md$ 7 | ^README_cache$ 8 | ^codecov\.yml$ 9 | ^README\.Rmd$ 10 | ^\.github$ 11 | ^README.md$ 12 | ^NEWS.md$ 13 | 14 | ^review\.md$ 15 | ^koppen climates$ 16 | ^phyloDist$ 17 | ^cran-comments\.md$ 18 | ^docs$ 19 | ^pkgdown$ 20 | ^Rplots\.pdf$ 21 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # CONTRIBUTING # 2 | 3 | ### Fixing typos 4 | 5 | Small typos or grammatical errors in documentation may be edited directly using 6 | the GitHub web interface, so long as the changes are made in the _source_ file. 7 | 8 | * YES: you edit a roxygen comment in a `.R` file below `R/`. 9 | * NO: you edit an `.Rd` file below `man/`. 10 | 11 | ### Prerequisites 12 | 13 | Before you make a substantial pull request, you should always file an issue and 14 | make sure someone from the team agrees that it’s a problem. If you’ve found a 15 | bug, create an associated issue and illustrate the bug with a minimal 16 | [reprex](https://www.tidyverse.org/help/#reprex). 17 | 18 | ### Pull request process 19 | 20 | * We recommend that you create a Git branch for each pull request (PR). 21 | * Look at the Travis and AppVeyor build status before and after making changes. 22 | The `README` should contain badges for any continuous integration services used 23 | by the package. 24 | * We recommend the tidyverse [style guide](http://style.tidyverse.org). 25 | You can use the [styler](https://CRAN.R-project.org/package=styler) package to 26 | apply these styles, but please don't restyle code that has nothing to do with 27 | your PR. 28 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2). 29 | * We use [testthat](https://cran.r-project.org/package=testthat). Contributions 30 | with test cases included are easier to accept. 31 | * For user-facing changes, add a bullet to the top of `NEWS.md` below the 32 | current development version header describing the changes made followed by your 33 | GitHub username, and links to relevant issue(s)/PR(s). 34 | 35 | ### Code of Conduct 36 | 37 | Please note that the {{{ package }}} project is released with a 38 | [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this 39 | project you agree to abide by its terms. 40 | 41 | ### See rOpenSci [contributing guide](https://devguide.ropensci.org/contributingguide.html) 42 | for further details. 43 | 44 | ### Discussion forum 45 | 46 | Check out our [discussion forum](https://discuss.ropensci.org) if you think your issue requires a longer form discussion. 47 | 48 | ### Prefer to Email? 49 | 50 | Email the person listed as maintainer in the `DESCRIPTION` file of this repo. 51 | 52 | Though note that private discussions over email don't help others - of course email is totally warranted if it's a sensitive problem of any kind. 53 | 54 | ### Thanks for contributing! 55 | 56 | This contributing guide is adapted from the tidyverse contributing guide available at https://raw.githubusercontent.com/r-lib/usethis/master/inst/templates/tidy-contributing.md 57 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Session Info 8 | 9 | ```r 10 | 11 | ``` 12 |
13 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ## Description 10 | 11 | 12 | ## Related Issue 13 | 16 | 17 | ## Example 18 | 20 | 21 | 23 | 24 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: R-CMD-check.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | R-CMD-check: 14 | runs-on: ${{ matrix.config.os }} 15 | 16 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | config: 22 | - {os: macos-latest, r: 'release'} 23 | - {os: windows-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'oldrel-1'} 27 | 28 | env: 29 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 30 | R_KEEP_PKG_SOURCE: yes 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - uses: r-lib/actions/setup-pandoc@v2 36 | 37 | - uses: r-lib/actions/setup-r@v2 38 | with: 39 | r-version: ${{ matrix.config.r }} 40 | http-user-agent: ${{ matrix.config.http-user-agent }} 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::rcmdcheck 46 | needs: check 47 | 48 | - uses: r-lib/actions/check-r-package@v2 49 | with: 50 | upload-snapshots: true 51 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 52 | -------------------------------------------------------------------------------- /.github/workflows/pr-commands.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | issue_comment: 3 | types: [created] 4 | name: Commands 5 | jobs: 6 | document: 7 | if: startsWith(github.event.comment.body, '/document') 8 | name: document 9 | runs-on: macOS-latest 10 | env: 11 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: r-lib/actions/pr-fetch@v1 15 | with: 16 | repo-token: ${{ secrets.GITHUB_TOKEN }} 17 | - uses: r-lib/actions/setup-r@v1 18 | - name: Install dependencies 19 | run: Rscript -e 'install.packages(c("remotes", "roxygen2"))' -e 'remotes::install_deps(dependencies = TRUE)' 20 | - name: Document 21 | run: Rscript -e 'roxygen2::roxygenise()' 22 | - name: commit 23 | run: | 24 | git config --local user.email "actions@github.com" 25 | git config --local user.name "GitHub Actions" 26 | git add man/\* NAMESPACE 27 | git commit -m 'Document' 28 | - uses: r-lib/actions/pr-push@v1 29 | with: 30 | repo-token: ${{ secrets.GITHUB_TOKEN }} 31 | style: 32 | if: startsWith(github.event.comment.body, '/style') 33 | name: style 34 | runs-on: macOS-latest 35 | env: 36 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 37 | steps: 38 | - uses: actions/checkout@v2 39 | - uses: r-lib/actions/pr-fetch@v1 40 | with: 41 | repo-token: ${{ secrets.GITHUB_TOKEN }} 42 | - uses: r-lib/actions/setup-r@v1 43 | - name: Install dependencies 44 | run: Rscript -e 'install.packages("styler")' 45 | - name: Style 46 | run: Rscript -e 'styler::style_pkg()' 47 | - name: commit 48 | run: | 49 | git config --local user.email "actions@github.com" 50 | git config --local user.name "GitHub Actions" 51 | git add \*.R 52 | git commit -m 'Style' 53 | - uses: r-lib/actions/pr-push@v1 54 | with: 55 | repo-token: ${{ secrets.GITHUB_TOKEN }} 56 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: test-coverage.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | test-coverage: 14 | runs-on: ubuntu-latest 15 | env: 16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - uses: r-lib/actions/setup-r@v2 22 | with: 23 | use-public-rspm: true 24 | 25 | - uses: r-lib/actions/setup-r-dependencies@v2 26 | with: 27 | extra-packages: any::covr, any::xml2 28 | needs: coverage 29 | 30 | - name: Test coverage 31 | run: | 32 | cov <- covr::package_coverage( 33 | quiet = FALSE, 34 | clean = FALSE, 35 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 36 | ) 37 | print(cov) 38 | covr::to_cobertura(cov) 39 | shell: Rscript {0} 40 | 41 | - uses: codecov/codecov-action@v4 42 | with: 43 | # Fail if error if not on PR, or if on PR and token is given 44 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }} 45 | file: ./cobertura.xml 46 | plugin: noop 47 | disable_search: true 48 | token: ${{ secrets.CODECOV_TOKEN }} 49 | 50 | - name: Show testthat output 51 | if: always() 52 | run: | 53 | ## -------------------------------------------------------------------- 54 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true 55 | shell: bash 56 | 57 | - name: Upload test results 58 | if: failure() 59 | uses: actions/upload-artifact@v4 60 | with: 61 | name: coverage-test-failures 62 | path: ${{ runner.temp }}/package 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tmp.Rmd 2 | tmp.sh 3 | .Rproj.user 4 | .Rhistory 5 | .RData 6 | inst/doc 7 | README_cache 8 | tmp.R 9 | .DS_Store 10 | data-raw/.DS_Store 11 | data-raw/csv_database/sitespecies_metadata.csv 12 | ship.sh 13 | tmp.md 14 | tmp_files 15 | .DS_Store 16 | docs 17 | Rplots.pdf 18 | 19 | /.quarto/ 20 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: allodb 2 | Title: Tree Biomass Estimation at Extra-Tropical Forest Plots 3 | Version: 0.0.1.9000 4 | Authors@R: c( 5 | person("Erika", "Gonzalez-Akre", , "ekagonzalez@gmail.com", role = c("aut", "cre", "cph"), 6 | comment = c(ORCID = "0000-0001-8305-6672")), 7 | person("Camille", "Piponiot", , "camille.piponiot@gmail.com", role = "aut", 8 | comment = c(ORCID = "0000-0002-3473-1982")), 9 | person("Mauro", "Lepore", , "maurolepore@gmail.com", role = "aut", 10 | comment = c(ORCID = "0000-0002-1986-7988")), 11 | person("Kristina", "Anderson-Teixeira", , "TeixeiraK@si.edu", role = "aut", 12 | comment = c(ORCID = "0000-0001-8461-9713")), 13 | person("Jeffrey", "Hanson", , "jeffrey.hanson@uqconnect.edu.au", role = "rev"), 14 | person("Jonas", "Stillhard", , "jonas.stillhard@wsl.ch", role = "rev") 15 | ) 16 | Description: Standardize and simplify the tree biomass estimation process 17 | across globally distributed extratropical forests. 18 | License: GPL-3 19 | URL: https://docs.ropensci.org/allodb/, https://github.com/ropensci/allodb 20 | BugReports: https://github.com/ropensci/allodb/issues 21 | Depends: 22 | R (>= 3.4) 23 | Imports: 24 | data.table, 25 | ggplot2, 26 | rlang, 27 | tibble, 28 | withr 29 | Suggests: 30 | covr, 31 | knitr, 32 | rmarkdown, 33 | spelling, 34 | testthat (>= 3.0.0), 35 | utils 36 | VignetteBuilder: 37 | knitr 38 | Config/testthat/edition: 3 39 | Encoding: UTF-8 40 | Language: en-US 41 | LazyData: true 42 | Roxygen: list(markdown = TRUE) 43 | RoxygenNote: 7.3.2 44 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(est_params) 4 | export(get_biomass) 5 | export(illustrate_allodb) 6 | export(new_equations) 7 | export(resample_agb) 8 | export(weight_allom) 9 | importFrom(rlang,abort) 10 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # allodb (development version) 2 | 3 | # allodb 0.0.1 4 | 5 | * Add support for R 3.4. 6 | 7 | * Incorporate peer-review suggestions as per 8 | https://github.com/ropensci/software-review/issues/436. 9 | -------------------------------------------------------------------------------- /R/allodb-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Tables of allometric equations and associated metadata 2 | #' 3 | #' A compilation of best available allometry equations to calculate tree 4 | #' above-ground biomass (AGB) per species based on extratropical ForestGEO 5 | #' sites. 6 | #' 7 | #' @description 8 | #'* [equations]: Table of allometric equations. 9 | #'* [equations_metadata]: Explanation of columns for [equations] table. 10 | #' 11 | #' @source See [references] for equations original sources. 12 | #' 13 | #' @family database datasets 14 | #' 15 | #' @examples 16 | #' # preview the datasets 17 | #' print(head(equations)) 18 | #' print(head(equations_metadata)) 19 | "equations" 20 | #' @rdname equations 21 | "equations_metadata" 22 | 23 | #' Explanations of missing values codes 24 | #' 25 | #' Explanation of the codes used to indicate missing information in equation 26 | #' table. 27 | #' 28 | #' @family database datasets 29 | #' 30 | #' @examples 31 | #' # preview the dataset 32 | #' print(head(missing_values)) 33 | "missing_values" 34 | 35 | #' Sites and tree species used in allodb and associated metadata 36 | #' 37 | #' * [sitespecies]: Table of extratropical ForestGEO sites in allodb (n=24) and 38 | #' their tree species. 39 | #' * [sitespecies_metadata]: Metadata for [sitespecies] table. 40 | #' 41 | #' @family database datasets 42 | #' 43 | #' @examples 44 | #' # preview the datasets 45 | #' print(head(sitespecies)) 46 | #' print(head(sitespecies_metadata)) 47 | "sitespecies" 48 | #' @rdname sitespecies 49 | "sitespecies_metadata" 50 | 51 | #' Equation references and associated metadata 52 | #' 53 | #' Bibliographical information for sourced equations. Links to the [equations] 54 | #' table by `ref_id`. 55 | #' 56 | #' @description 57 | #' * [references]: A data frame listing all references used in `equation` table. 58 | #' * [references_metadata]: Metadata for `reference` table. 59 | #' 60 | #' @family database datasets 61 | #' 62 | #' @examples 63 | #' # preview the datasets 64 | #' print(head(references)) 65 | #' print(head(references_metadata)) 66 | "references" 67 | #' @rdname references 68 | "references_metadata" 69 | 70 | #' ForestGEO sites used in allodb 71 | #' 72 | #' Table with geographical information for extratropical ForestGEO sites used in 73 | #' allodb (n=24). 74 | #' 75 | #' More details on geographical aspects of these ForestGEO sites can be found in 76 | #' the accompanying manuscript. 77 | #' 78 | #' @family database datasets 79 | #' 80 | #' @examples 81 | #' # preview the datasets 82 | #' print(head(sites_info)) 83 | "sites_info" 84 | 85 | #' Tree census data from SCBI ForestGEO plot 86 | #' 87 | #' A table with tree data from the Smithsonian Conservation Biology Institute, 88 | #' USA (SCBI) ForestGEO dynamics plot. This dataset is an extract from the first 89 | #' tree census in 2008, only covering 1 hectare (SCBI plot is 25.6 ha). DBH in 90 | #' cm. 91 | #' 92 | #' @source Full datasets for tree census data at SCBI can be requested through 93 | #' the ForestGEO portal (). Census 1, 2, and 3 can 94 | #' also be accessed at the public GitHub repository for SCBI-ForestGEO Data 95 | #' (). 96 | #' 97 | #' @family datasets 98 | #' 99 | #' @examples 100 | #' # preview the datasets 101 | #' print(head(scbi_stem1)) 102 | "scbi_stem1" 103 | 104 | #' Genus and family table for selected ForestGEO sites 105 | #' 106 | #' Genus and their associated family identified in the extratropical ForestGEO 107 | #' sites used in allodb. 108 | #' 109 | #' @family datasets 110 | #' 111 | #' @examples 112 | #' # preview the dataset 113 | #' print(head(genus_family)) 114 | "genus_family" 115 | 116 | #' Gymnosperms identified in selected ForestGEO sites 117 | #' 118 | #' Table with genus and their associated family for Gymnosperms identified in 119 | #' the ForestGEO sites used in allodb. 120 | #' 121 | #' @family datasets 122 | #' 123 | #' @examples 124 | #' # preview the dataset 125 | #' print(head(gymno_genus)) 126 | "gymno_genus" 127 | 128 | #' Shrub species identified in selected ForestGEO sites 129 | #' 130 | #' Genus and species of shrubby plants identified in the 24 extratropical 131 | #' ForestGEO sites used in allodb. 132 | #' 133 | #' @family datasets 134 | #' 135 | #' @examples 136 | #' # preview the dataset 137 | #' print(head(shrub_species)) 138 | "shrub_species" 139 | 140 | #' Koppen climate classification matrix 141 | #' 142 | #' A table built to facilitate the comparison between the Koppen climate of a 143 | #' site and the allometric equation in question. 144 | #' 145 | #' The value of column `we` is the weight given to the combination of Koppen 146 | #' climates in columns `zone1` and `zone2`; the table is symmetric: `zone1` and 147 | #' `zone2` can be interchanged. This weight is calculated in 3 steps: (1) if the 148 | #' main climate group (first letter) is the same, the climate weight starts at 149 | #' 0.4; if one of the groups is "C" (temperate climate) and the other is "D" 150 | #' (continental climate), the climate weight starts at 0.2 because the 2 groups 151 | #' are considered similar enough; otherwise, the weight is 0; (2) if the 152 | #' equation and site belong to the same group, the weight is incremented by an 153 | #' additional value between 0 and 0.3 based on precipitation pattern similarity 154 | #' (second letter of the Koppen zone), and (3) by an additional value between 0 155 | #' and 0.3 based on temperature pattern similarity (third letter of the Koppen 156 | #' zone). The resulting weight has a value between 0 (different climate groups) 157 | #' and 1 (exactly the same climate classification). 158 | #' 159 | #' @family datasets 160 | #' 161 | #' @examples 162 | #' # preview the dataset 163 | #' print(head(koppenMatrix)) 164 | "koppenMatrix" 165 | -------------------------------------------------------------------------------- /R/est_params.R: -------------------------------------------------------------------------------- 1 | #' Calibrate new allometric equations 2 | #' 3 | #' This function calibrates new allometric equations from sampling previous 4 | #' ones. New allometric equations are calibrated for each species and location 5 | #' by resampling the original compiled equations; equations with a larger sample 6 | #' size, and/or higher taxonomic rank, and climatic similarity with the species 7 | #' and location in question are given a higher weight in this process. 8 | #' 9 | #' @param genus a character vector, containing the genus (e.g. "Quercus") of 10 | #' each tree. 11 | #' @param coords a numeric vector of length 2 with longitude and latitude (if 12 | #' all trees were measured in the same location) or a matrix with 2 numerical 13 | #' columns giving the coordinates of each tree. 14 | #' @param species a character vector (same length as genus), containing the 15 | #' species (e.g. "rubra") of each tree. Default is `NULL`, when no species 16 | #' identification is available. 17 | #' @param new_eqtable Optional. An equation table created with the 18 | #' [new_equations()] function. Default is the compiled *allodb* equation 19 | #' table. 20 | #' @param wna a numeric vector, this parameter is used in the [weight_allom()] 21 | #' function to determine the dbh-related and sample-size related weights 22 | #' attributed to equations without a specified dbh range or sample size, 23 | #' respectively. Default is 0.1. 24 | #' @param w95 a numeric vector, this parameter is used in the [weight_allom()] 25 | #' function to determine the value at which the sample-size-related weight 26 | #' reaches 95% of its maximum value (max=1). Default is 500. 27 | #' @param nres number of resampled values. Default is "1e4". 28 | #' 29 | #' @return An object of class "data.frame" of fitted coefficients (columns) of 30 | #' the non-linear least-square regression: 31 | #' \deqn{AGB = a * dbh ^ b + e, \space 32 | #' \mathit{with} \space e ~ N(0, sigma^2)}{AGB = a * dbh ^ b + e, with e ~ 33 | #' N(0, sigma^2)} 34 | #' 35 | #' @seealso [weight_allom()], [new_equations()]. 36 | #' 37 | #' @export 38 | #' 39 | #' @examples 40 | #' # calibrate new allometries for all Lauraceae species 41 | #' lauraceae <- subset(scbi_stem1, Family == "Lauraceae") 42 | #' est_params( 43 | #' genus = lauraceae$genus, 44 | #' species = lauraceae$species, 45 | #' coords = c(-78.2, 38.9) 46 | #' ) 47 | est_params <- function(genus, 48 | coords, 49 | species = NULL, 50 | new_eqtable = NULL, 51 | wna = 0.1, 52 | w95 = 500, 53 | nres = 1e4) { 54 | if (!is.null(new_eqtable)) { 55 | dfequation <- new_eqtable 56 | } else { 57 | dfequation <- new_equations() 58 | } 59 | 60 | ## get all combinations of species x site 61 | if (length(unlist(coords)) == 2) { 62 | coords <- t(as.numeric(coords)) 63 | } 64 | colnames(coords) <- c("long", "lat") 65 | dfobs <- unique(data.table::data.table(genus, species, coords)) 66 | 67 | coefs <- c() 68 | for (i in seq_len(nrow(dfobs))) { 69 | df <- resample_agb( 70 | genus = dfobs$genus[i], 71 | species = dfobs$species[i], 72 | coords = dfobs[i, c("long", "lat")], 73 | new_eqtable = dfequation, 74 | wna = wna, 75 | w95 = w95, 76 | nres = nres 77 | ) 78 | # special case: only one equation is resampled and it's of the form a*x^b 79 | # nls will throw an error: add some 'grain' by adding 1 slightly different 80 | # data point (it won't change the final results) 81 | if (length(unique(df$equation_id)) == 1) df[1, 3] <- df[1, 3] * 1.01 82 | reg <- summary(stats::nls(agb ~ a * dbh**b, 83 | start = c(a = 0.5, b = 2), data = df 84 | )) 85 | coefs <- rbind(coefs, c(reg$coefficients[, "Estimate"], reg$sigma)) 86 | } 87 | colnames(coefs) <- c("a", "b", "sigma") 88 | 89 | return(tibble::as_tibble(cbind(dfobs, coefs))) 90 | } 91 | -------------------------------------------------------------------------------- /R/get_biomass.R: -------------------------------------------------------------------------------- 1 | #' Compute tree aboveground biomass (AGB) based on allometric equations 2 | #' 3 | #' This function calculates the aboveground biomass (or other tree components) 4 | #' of a given tree based on published allometric equations. Users need to 5 | #' provide a table (i.e. dataframe) with DBH (cm), parsed species Latin names, 6 | #' and site(s) coordinates. The biomass of all trees in one (or several) 7 | #' censuses can be estimated using this function. 8 | #' 9 | #' `allodb` estimates AGB by calibrating a new allometric equation for each 10 | #' taxon (arguments `genus` and `species`) and location (argument `coords`) in 11 | #' the user-provided census data. The new allometric equation is based on a set 12 | #' of allometric equations that can be customized using the `new_eqtable` 13 | #' argument. Each equation is then given a weight with the [weight_allom()] 14 | #' function, based on: 1) its original sample size (numbers of trees used to 15 | #' develop a given allometry), 2) its climatic similarity with the target 16 | #' location, and 3) its taxonomic similarity with the target taxon (see 17 | #' documentation of the [weight_allom()] function). The final weight attributed 18 | #' to each equation is the product of those three weights. Equations are then 19 | #' resampled with the[resample_agb()] function: the number of samples per 20 | #' equation is proportional to its weight, and the total number of samples is 21 | #' provided by the argument `nres`. The resampling is done by drawing DBH values 22 | #' from a uniform distribution on the DBH range of the equation, and estimating 23 | #' the AGB with the equation. The couples of values (DBH, AGB) obtained are then 24 | #' used in the function [est_params()] to calibrate a new allometric equation, 25 | #' by applying a linear regression to the log-transformed data. The parameters 26 | #' of the new allometric equations are then used in the [get_biomass()] function 27 | #' by back-transforming the AGB predictions based on the user-provided DBHs. 28 | #' 29 | #' @section Warning: 30 | #' The function can run into some memory problems when used on large datasets 31 | #' (usually several hundred thousand observations). 32 | #' 33 | #' @param dbh a numeric vector containing tree diameter at breast height (dbh) 34 | #' measurements, in cm. 35 | #' @param genus a character vector (same length as dbh), containing the genus 36 | #' (e.g. "Quercus") of each tree. 37 | #' @param coords a numeric vector of length 2 with longitude and latitude (if 38 | #' all trees were measured in the same location) or a matrix with 2 numerical 39 | #' columns giving the coordinates of each tree. 40 | #' @param species a character vector (same length as dbh), containing the 41 | #' species (e.g. "rubra") of each tree. Default is `NULL`, when no species 42 | #' identification is available. 43 | #' @param new_eqtable Optional. An equation table created with the 44 | #' [new_equations()] function. 45 | #' @param wna a numeric vector, this parameter is used in the [weight_allom()] 46 | #' function to determine the dbh-related weight attributed to equations 47 | #' without a specified dbh range. Default is 0.1. 48 | #' @param w95 a numeric vector, this parameter is used in the [weight_allom()] 49 | #' function to determine the value at which the sample-size-related weight 50 | #' reaches 95% of its maximum value (max=1). Default is 500. 51 | #' @param nres number of resampled values. Default is "1e4". 52 | #' 53 | #' @return A "numeric" vector of the same length as dbh, containing AGB value 54 | #' (in kg) for every stem. 55 | #' 56 | #' @seealso [weight_allom()], [new_equations()] 57 | #' 58 | #' @export 59 | #' 60 | #' @examples 61 | #' # Estimate biomass of all individuals from the Lauraceae family at the SCBI 62 | #' # plot 63 | #' lau <- subset(scbi_stem1, Family == "Lauraceae") 64 | #' lau$agb <- get_biomass(lau$dbh, lau$genus, lau$species, 65 | #' coords = c(-78.2, 38.9) 66 | #' ) 67 | #' lau 68 | #' 69 | #' # Estimate biomass from multiple sites (using scbi_stem1 as example with 70 | #' # multiple coord) 71 | #' dat <- scbi_stem1[1:100, ] 72 | #' dat$long <- c(rep(-78, 50), rep(-80, 50)) 73 | #' dat$lat <- c(rep(40, 50), rep(41, 50)) 74 | #' dat$biomass <- get_biomass( 75 | #' dbh = dat$dbh, 76 | #' genus = dat$genus, 77 | #' species = dat$species, 78 | #' coords = dat[, c("long", "lat")] 79 | #' ) 80 | #' dat 81 | get_biomass <- function(dbh, 82 | genus, 83 | coords, 84 | species = NULL, 85 | new_eqtable = NULL, 86 | wna = 0.1, 87 | w95 = 500, 88 | nres = 1e4) { 89 | if (!is.null(new_eqtable)) { 90 | dfequation <- new_eqtable 91 | } else { 92 | dfequation <- new_equations() 93 | } 94 | 95 | if (length(unlist(coords)) == 2) { 96 | coords <- matrix(coords, ncol = 2) 97 | } 98 | colnames(coords) <- c("long", "lat") 99 | 100 | ## input data checks 101 | if (any(!is.na(dbh) & (dbh < 0 | dbh > 1e3))) { 102 | abort(c( 103 | "Each value of `dbh` must be positive and < 1000 cm.", 104 | i = "Do you need to check your data?" 105 | )) 106 | } 107 | if (any(abs(coords[, 1]) > 180 | abs(coords[, 2]) > 90)) { 108 | abort(c( 109 | "`coords` longitudes must range -180 to 180, and latitudes -90 to 90.", 110 | i = "Do you need to check your data?" 111 | )) 112 | } 113 | 114 | params <- 115 | est_params( 116 | genus = genus, 117 | coords = coords, 118 | species = species, 119 | new_eqtable = dfequation, 120 | wna = wna, 121 | w95 = w95, 122 | nres = nres 123 | ) 124 | 125 | if (!is.null(species)) { 126 | data <- tibble::tibble( 127 | id = seq_len(length(dbh)), 128 | dbh, 129 | genus, 130 | species, 131 | long = coords[[1]], 132 | lat = coords[[2]] 133 | ) 134 | df <- 135 | merge( 136 | data, 137 | params, 138 | by = c("genus", "species", "long", "lat") 139 | ) 140 | } else { 141 | df <- merge(data.frame(stringsAsFactors = FALSE, id = seq_len(length(dbh)), dbh, genus, coords), 142 | params, 143 | by = c("genus", "long", "lat") 144 | ) 145 | } 146 | 147 | df <- df[order(df$id), ] 148 | agb <- df$a * df$dbh^df$b 149 | 150 | return(agb) 151 | } 152 | -------------------------------------------------------------------------------- /R/illustrate_allodb.R: -------------------------------------------------------------------------------- 1 | #' Illustrate the resampling of AGB values used in *allodb* 2 | #' 3 | #' This function illustrates the resampling of AGB values used in *allodb*. It 4 | #' creates objects of class "ggplot". 5 | #' 6 | #' @param genus A character value, containing the genus (e.g. "Quercus") of the 7 | #' tree. 8 | #' @param coords A numeric vector of length 2 with longitude and latitude. 9 | #' @param species A character value, containing the species (e.g. "rubra") of 10 | #' the tree. Default is `NULL`, when no species identification is available. 11 | #' @param new_eqtable Optional. An equation table created with the 12 | #' [new_equations()] function. Default is the base *allodb* equation 13 | #' table. 14 | #' @param logxy Logical: should values be plotted on a log scale? Default is 15 | #' `FALSE`. 16 | #' @param neq Number of top equations in the legend. Default is 10, meaning that 17 | #' the 10 equations with the highest weights are shown in the legend. 18 | #' @param eqinfo Which column(s) of the equation table should be used in the 19 | #' legend? Default is "equation_taxa". 20 | #' @param wna a numeric vector, this parameter is used in the [weight_allom()] 21 | #' function to determine the dbh-related and sample-size related weights 22 | #' attributed to equations without a specified dbh range or sample size, 23 | #' respectively. Default is 0.1. 24 | #' @param w95 a numeric vector, this parameter is used in the [weight_allom()] 25 | #' function to determine the value at which the sample-size-related weight 26 | #' reaches 95% of its maximum value (max=1). Default is 500. 27 | #' @param nres number of resampled values. Default is "1e4". 28 | #' 29 | #' @return An object of class "ggplot" showing all resampled dbh-agb values. The 30 | #' top equations used are shown in the legend. The red curve on the graph 31 | #' represents the final fitted equation. 32 | #' 33 | #' @seealso [weight_allom()], [new_equations()]. 34 | #' 35 | #' @export 36 | #' 37 | #' @examples 38 | #' illustrate_allodb( 39 | #' genus = "Quercus", 40 | #' species = "rubra", 41 | #' coords = c(-78.2, 38.9) 42 | #' ) 43 | illustrate_allodb <- function(genus, 44 | coords, 45 | species = NULL, 46 | new_eqtable = NULL, 47 | logxy = FALSE, 48 | neq = 10, 49 | eqinfo = "equation_taxa", 50 | wna = 0.1, 51 | w95 = 500, 52 | nres = 1e4) { 53 | dfagb <- 54 | resample_agb( 55 | genus = genus, 56 | coords = coords, 57 | species = species, 58 | new_eqtable = new_eqtable, 59 | wna = wna, 60 | w95 = w95, 61 | nres = nres 62 | ) 63 | params <- 64 | est_params( 65 | genus = genus, 66 | coords = coords, 67 | species = species, 68 | new_eqtable = new_eqtable, 69 | wna = wna, 70 | w95 = w95, 71 | nres = nres 72 | ) 73 | pred <- function(x) params$a * x**params$b 74 | 75 | if (is.null(new_eqtable)) { 76 | equations <- new_equations() 77 | } else { 78 | equations <- new_eqtable 79 | } 80 | 81 | ## get equation info 82 | eq_info <- apply( 83 | equations[, c("equation_id", eqinfo)], 1, 84 | function(x) { 85 | paste(x, collapse = " - ") 86 | } 87 | ) 88 | eq_info <- 89 | tibble::tibble(equation_id = equations$equation_id, equation = eq_info) 90 | 91 | data <- table(equation_id = dfagb$equation_id) 92 | dfcounts <- tibble::tibble(equation_id = names(data), Freq = unname(data)) 93 | 94 | eq_info <- merge(eq_info, dfcounts, by = "equation_id") 95 | eq_info <- eq_info[order(eq_info$Freq, decreasing = TRUE), ] 96 | eq_info[(neq + 1):nrow(eq_info), "equation"] <- "other" 97 | eq_info$equation <- 98 | factor(eq_info$equation, levels = unique(eq_info$equation)) 99 | dfagb <- merge(dfagb, eq_info, by = "equation_id") 100 | 101 | g <- ggplot2::ggplot(dfagb, ggplot2::aes(x = dbh, y = agb)) + 102 | ggplot2::geom_point( 103 | data = subset(dfagb, equation == "other"), 104 | alpha = 0.2 105 | ) + 106 | ggplot2::geom_point( 107 | data = subset(dfagb, equation != "other"), 108 | ggplot2::aes(col = equation) 109 | ) + 110 | ggplot2::stat_function( 111 | fun = pred, 112 | lwd = 2, 113 | col = 2, 114 | lty = 2 115 | ) + 116 | ggplot2::theme_classic() + 117 | ggplot2::labs( 118 | x = "DBH (cm)", 119 | y = "AGB (kg)", 120 | colour = "Top resampled equations" 121 | ) 122 | if (logxy) { 123 | g <- g + 124 | ggplot2::scale_x_log10() + 125 | ggplot2::scale_y_log10() 126 | } 127 | g 128 | } 129 | -------------------------------------------------------------------------------- /R/imports.R: -------------------------------------------------------------------------------- 1 | #' @importFrom rlang abort 2 | NULL 3 | 4 | globalVariables( 5 | c( 6 | "Lat", 7 | "Lon", 8 | "agb", 9 | "dbh", 10 | "dependent_variable", 11 | "equation", 12 | "equation_id", 13 | "equations", 14 | "independent_variable", 15 | "ref_id", 16 | "resample", 17 | "zone1", 18 | "zone2" 19 | ) 20 | ) 21 | -------------------------------------------------------------------------------- /R/new_equations.R: -------------------------------------------------------------------------------- 1 | #' Modify the original equation table 2 | #' 3 | #' This function modifies the original equation table to be used in other 4 | #' functions of the package including: subset the original equation table, add 5 | #' new equations, and choose whether to include equations with a height 6 | #' allometry. 7 | #' 8 | #' @param subset_taxa character vector with taxa to be kept. Default is "all", 9 | #' in which case all taxa are kept. 10 | #' @param subset_climate character vector with Koppen climate classification to 11 | #' be kept. Default is "all", in which case all climates are kept. 12 | #' @param subset_region character vector with name of location(s) or 13 | #' country(ies) or broader region(s) (eg. "Europe", "North America") to be 14 | #' kept. Default is "all", in which case all regions/countries are kept. 15 | #' @param subset_ids character vector with equation IDs to be kept. Default is 16 | #' "all", in which case all equations are kept. 17 | #' @param subset_output What dependent variable(s) should be provided in the 18 | #' output? Default is "Total aboveground biomass" and "Whole tree (above 19 | #' stump)", other possible values are: "Bark biomass", "Branches (dead)", 20 | #' "Branches (live)", "Branches total (live, dead)", "Foliage total", 21 | #' "Height", "Leaves", "Stem (wood only)", "Stem biomass", "Stem biomass (with 22 | #' bark)", "Stem biomass (without bark)", "Whole tree (above and 23 | #' belowground)". Be aware that currently only a few equations represent those 24 | #' other variables, so estimated values might not be very accurate. 25 | #' @param new_taxa character string or vector specifying the taxon (or taxa) for 26 | #' which the allometry has been calibrated. 27 | #' @param new_allometry a character string with the allometric equation. 28 | #' @param new_coords a vector or matrix of coordinates (longitude, latitude) of 29 | #' the calibration data. 30 | #' @param new_min_dbh numerical value, minimum DBH for which the equation is 31 | #' valid (in cm). Default is `NULL` (nothing is added). 32 | #' @param new_max_dbh numerical value, maximum DBH for which the equation is 33 | #' valid (in cm). Default is `NULL` (nothing is added). 34 | #' @param new_sample_size number of measurements with which the allometry was 35 | #' calibrated. Default is `NULL` (nothing is added). 36 | #' @param new_unit_dbh character string with unit of DBH in the equation (either 37 | #' `cm`, `mm` or `inch`). Default is "cm". 38 | #' @param new_unit_output character string with unit of equation output (either 39 | #' "g", "kg", "Mg" or "lbs" if the output is a mass, or "m" if the output is a 40 | #' height). 41 | #' @param new_input_var independent variable(s) needed in the allometry. Default 42 | #' is "DBH", other option is "DBH, H". 43 | #' @param new_output_var dependent variable estimated by the allometry. Default 44 | #' is "Total aboveground biomass". 45 | #' @param use_height_allom a logical value. In *allodb* we use Bohn et al. 46 | #' (2014) for European sites. User need to provide height allometry when 47 | #' needed to calculate AGB. Default is `TRUE`. 48 | #' 49 | #' @return An object of class "data.frame" of new equations. 50 | #' 51 | #' @export 52 | #' 53 | #' @examples 54 | #' new_equations( 55 | #' new_taxa = "Faga", 56 | #' new_allometry = "exp(-2+log(dbh)*2.5)", 57 | #' new_coords = c(-0.07, 46.11), 58 | #' new_min_dbh = 5, 59 | #' new_max_dbh = 50, 60 | #' new_sample_size = 50 61 | #' ) 62 | new_equations <- function(subset_taxa = "all", 63 | subset_climate = "all", 64 | subset_region = "all", 65 | subset_ids = "all", 66 | subset_output = c( 67 | "Total aboveground biomass", 68 | "Whole tree (above stump)" 69 | ), 70 | new_taxa = NULL, 71 | new_allometry = NULL, 72 | new_coords = NULL, 73 | new_min_dbh = NULL, 74 | new_max_dbh = NULL, 75 | new_sample_size = NULL, 76 | new_unit_dbh = "cm", 77 | new_unit_output = "kg", 78 | new_input_var = "DBH", 79 | new_output_var = "Total aboveground biomass", 80 | use_height_allom = TRUE) { 81 | ## open the equation table and get it in the right format #### 82 | equations_orig <- allodb::equations 83 | colnames(equations_orig) <- tolower(colnames(equations_orig)) 84 | new_equations <- equations_orig 85 | 86 | suppressWarnings(new_equations$dbh_min_cm <- 87 | as.numeric(new_equations$dbh_min_cm)) 88 | suppressWarnings(new_equations$dbh_max_cm <- 89 | as.numeric(new_equations$dbh_max_cm)) 90 | suppressWarnings(new_equations$sample_size <- 91 | as.numeric(new_equations$sample_size)) 92 | suppressWarnings(new_equations$dbh_unit_cf <- 93 | as.numeric(new_equations$dbh_unit_cf)) 94 | suppressWarnings(new_equations$output_units_cf <- 95 | as.numeric(new_equations$output_units_cf)) 96 | 97 | ## replace height with height allometry #### from Bohn et al. 2014 in Jansen 98 | ## et al. 1996 99 | if (use_height_allom & 100 | "jansen_1996_otvb" %in% new_equations$ref_id) { 101 | eq_jansen <- subset(new_equations, ref_id == "jansen_1996_otvb") 102 | ## height allometries defined per genus -> get info in Jansen allometries 103 | eq_jansen$genus <- 104 | data.table::tstrsplit(eq_jansen$equation_notes, " ")[[5]] 105 | ## create height allometry dataframe 106 | hallom <- 107 | subset( 108 | new_equations, 109 | ref_id == "bohn_2014_ocai" & 110 | dependent_variable == "Height" 111 | ) 112 | hallom <- hallom[, c("equation_taxa", "equation_allometry")] 113 | colnames(hallom) <- c("genus", "hsub") 114 | ## merge with jansen allometries (equations that do not have a corresponding 115 | ## height allometry will not be substituted) 116 | eq_jansen <- merge(eq_jansen, hallom, by = "genus") 117 | # substitute H by its DBH-based estimation 118 | to_merge <- eq_jansen[, c("hsub", "equation_allometry")] 119 | eq_jansen$equation_allometry <- apply(to_merge, 1, function(xx) { 120 | gsub("\\(h", paste0("((", xx[1], ")"), xx[2]) 121 | }) 122 | # replace independent_variable column 123 | eq_jansen$independent_variable <- "DBH" 124 | # replace in equation table 125 | new_equations <- 126 | rbind( 127 | subset(new_equations, !equation_id %in% eq_jansen$equation_id), 128 | eq_jansen[, colnames(new_equations)] 129 | ) 130 | } else { 131 | new_equations <- 132 | subset(new_equations, independent_variable == "DBH") 133 | } 134 | 135 | ## subset equation table #### 136 | if (any(subset_taxa != "all")) { 137 | keep <- vapply(new_equations$equation_taxa, function(tax0) { 138 | any(vapply(subset_taxa, function(i) { 139 | grepl(i, tax0) 140 | }, FUN.VALUE = TRUE)) 141 | }, FUN.VALUE = TRUE) 142 | new_equations <- new_equations[keep, ] 143 | } 144 | 145 | if (any(subset_climate != "all")) { 146 | keep <- vapply(new_equations$koppen, function(clim0) { 147 | any(vapply(subset_climate, function(i) { 148 | grepl(i, clim0) 149 | }, FUN.VALUE = TRUE)) 150 | }, FUN.VALUE = TRUE) 151 | new_equations <- new_equations[keep, ] 152 | } 153 | 154 | if (any(subset_region != "all")) { 155 | keep <- vapply(new_equations$geographic_area, function(reg0) { 156 | any(vapply(subset_region, function(i) { 157 | grepl(i, reg0) 158 | }, FUN.VALUE = TRUE)) 159 | }, FUN.VALUE = TRUE) 160 | new_equations <- new_equations[keep, ] 161 | } 162 | 163 | if (any(subset_ids != "all")) { 164 | new_equations <- subset(new_equations, equation_id %in% subset_ids) 165 | } 166 | 167 | new_equations <- 168 | subset(new_equations, dependent_variable %in% subset_output) 169 | 170 | ## add new equations #### 171 | # check that new allometry was added 172 | if (is.null(new_allometry) & (!is.null(new_taxa) | !is.null(new_coords))) { 173 | abort(c( 174 | "`new_allometry` must not be `NULL`", 175 | i = "Did you forget to add the new allometry?" 176 | )) 177 | } 178 | 179 | if (!is.null(new_allometry)) { 180 | ## check consistency of inputs 181 | if (is.null(new_taxa) | 182 | is.null(new_coords) | 183 | is.null(new_min_dbh) | 184 | is.null(new_max_dbh) | 185 | is.null(new_sample_size)) { 186 | abort( 187 | "You must provide the taxa, coordinates, DBH range 188 | and sample size of you new allometries." 189 | ) 190 | } 191 | 192 | if (!is.numeric(new_min_dbh) | 193 | !is.numeric(new_max_dbh) | !is.numeric(new_sample_size)) { 194 | abort( 195 | "`new_min_dbh`, `new_max_dbh`, and `new_sample_size` must be numeric." 196 | ) 197 | } 198 | 199 | if (is.matrix(new_coords)) { 200 | ncoords <- ncol(new_coords) 201 | } else { 202 | ncoords <- length(new_coords) 203 | } 204 | if (!is.numeric(new_coords) | ncoords != 2) { 205 | abort( 206 | "`coords` must be a numeric vector or matrix, with 2 values or columns." 207 | ) 208 | } 209 | 210 | if (length(new_taxa) != length(new_allometry) | 211 | length(new_allometry) != length(new_min_dbh) | 212 | length(new_min_dbh) != length(new_max_dbh) | 213 | length(new_max_dbh) != length(new_sample_size)) { 214 | abort(c( 215 | "All of these arguments must have the same length:", 216 | "`new_taxa`", 217 | "`new_allometry`", 218 | "`new_min_dbh`", 219 | "`new_max_dbh`", 220 | "`new_sample_size`" 221 | )) 222 | } 223 | 224 | if (!is.character(new_allometry)) { 225 | abort("The equation allometry should be a character vector.") 226 | } 227 | if (any(grepl("=|<-", new_allometry))) { 228 | abort("`new_allometry` must be a function of dbh (e.g. '0.5 * dbh^2').") 229 | } 230 | dbh <- 10 231 | eval(parse(text = tolower(new_allometry))) 232 | 233 | if (!new_unit_dbh %in% c("cm", "mm", "inch")) { 234 | abort("`new_unit_dbh` must be in 'cm', 'mm' or 'inch'.") 235 | } 236 | 237 | if (!new_unit_output %in% c("g", "kg", "Mg", "lbs", "m")) { 238 | abort("`new_unit_output` must be 'g', 'kg', 'Mg' or 'lbs', or 'm'.") 239 | } 240 | 241 | if (new_output_var == "Height" & new_unit_output != "m") { 242 | abort("Height allometries outputs must be in 'm'.") 243 | } 244 | 245 | if (any(new_max_dbh <= new_min_dbh) | 246 | any(new_min_dbh < 0) | 247 | any(!is.numeric(new_min_dbh)) | 248 | any(!is.numeric(new_max_dbh))) { 249 | abort( 250 | "`new_max_dbh` must greater than `new_min_dbh` and both not negative." 251 | ) 252 | } 253 | 254 | if (!is.matrix(new_coords)) { 255 | new_coords <- 256 | matrix(rep(new_coords, length(new_taxa)), 257 | ncol = 2, 258 | byrow = TRUE 259 | ) 260 | } 261 | # FIXME: `!is.numeric(new_coords)` triggers another error at line 202 262 | if (!is.numeric(new_coords) | 263 | !(ncol(new_coords) == 2 & 264 | nrow(new_coords) == length(new_taxa))) { 265 | abort(paste( 266 | "`new_coords` must be a numeric vector of length 2 or a matrix with 2", 267 | "columns (long, lat) and as many rows as the number of equations." 268 | )) 269 | } 270 | 271 | if (any(new_coords[, 1] < -180 | 272 | new_coords[, 1] > 180 | 273 | new_coords[, 2] < -90 | new_coords[, 2] > 90)) { 274 | abort( 275 | "Longitude must be between -180 and 180, and latitude between 90 and 0." 276 | ) 277 | } 278 | 279 | new_allometry <- tolower(new_allometry) 280 | 281 | if (any(!grepl("dbh", new_allometry))) { 282 | abort("Each new allometry must contain DBH as a dependent variable.") 283 | } 284 | 285 | new_equation_id <- paste0("new", seq_len(length(new_taxa))) 286 | coords_eq <- cbind( 287 | long = new_coords[, 1], 288 | lat = new_coords[, 2] 289 | ) 290 | rcoords_eq <- round(coords_eq * 2 - 0.5) / 2 + 0.25 291 | ## extract koppen climate of every location 292 | koppen_zones <- apply(rcoords_eq, 1, function(k) { 293 | subset(climatezones, Lon == k[1] & Lat == k[2])$Cls 294 | }) 295 | koppen_zones <- as.character(unlist(koppen_zones)) 296 | if (length(koppen_zones) != nrow(rcoords_eq)) { 297 | abort(c( 298 | "Can't find all koppen climate zones based on coordinates", 299 | i = "Do you need to check that they are Long, Lat?" 300 | )) 301 | } 302 | 303 | added_equations <- tibble::tibble( 304 | equation_id = new_equation_id, 305 | equation_taxa = new_taxa, 306 | equation_allometry = new_allometry, 307 | independent_variable = new_input_var, 308 | dependent_variable = new_output_var, 309 | long = new_coords[, 1], 310 | lat = new_coords[, 2], 311 | koppen = koppen_zones, 312 | dbh_min_cm = new_min_dbh, 313 | dbh_max_cm = new_max_dbh, 314 | sample_size = new_sample_size, 315 | dbh_units_original = new_unit_dbh, 316 | output_units_original = new_unit_output 317 | ) 318 | 319 | new_equations <- rbind( 320 | added_equations, 321 | new_equations[, colnames(added_equations)] 322 | ) 323 | 324 | ## add conversion factors 325 | dbh_cf <- 326 | unique(equations_orig[, c("dbh_units_original", "dbh_unit_cf")]) 327 | output_cf <- 328 | unique(equations_orig[, c("output_units_original", "output_units_cf")]) 329 | suppressWarnings(dbh_cf$dbh_unit_cf <- 330 | as.numeric(dbh_cf$dbh_unit_cf)) 331 | suppressWarnings(output_cf$output_units_cf <- 332 | as.numeric(output_cf$output_units_cf)) 333 | new_equations <- merge(new_equations, dbh_cf) 334 | new_equations <- merge(new_equations, output_cf) 335 | 336 | new_equations <- new_equations[, c( 337 | "equation_id", 338 | "equation_taxa", 339 | "equation_allometry", 340 | "independent_variable", 341 | "dependent_variable", 342 | "long", 343 | "lat", 344 | "koppen", 345 | "dbh_min_cm", 346 | "dbh_max_cm", 347 | "sample_size", 348 | "dbh_units_original", 349 | "dbh_unit_cf", 350 | "output_units_original", 351 | "output_units_cf" 352 | )] 353 | } 354 | 355 | return(tibble::as_tibble(new_equations)) 356 | } 357 | -------------------------------------------------------------------------------- /R/resample_agb.R: -------------------------------------------------------------------------------- 1 | #' Resample *allodb* equations to calibrate new allometries 2 | #' 3 | #' After attributing a weight to each equation in *allodb* using the 4 | #' [weight_allom()] function, equations are then resampled within their original 5 | #' DBH range using [resample_agb()]: the number of resampled values for each 6 | #' equation is proportional to its weight. It creates S3 objects of class 7 | #' "numeric". 8 | #' 9 | #' @param genus a character value, containing the genus (e.g. "Quercus") of the 10 | #' tree. 11 | #' @param coords a numeric vector of length 2 with longitude and latitude. 12 | #' @param species a character value, containing the species (e.g. "rubra") of 13 | #' the tree. Default is "NULL", when no species identification is available. 14 | #' @param new_eqtable Optional. An equation table created with the 15 | #' [new_equations()] function. Default is the original *allodb* equation 16 | #' table. 17 | #' @param wna a numeric vector, this parameter is used in the [weight_allom()] 18 | #' function to determine the dbh-related and sample-size related weights 19 | #' attributed to equations without a specified dbh range or sample size, 20 | #' respectively. Default is 0.1. 21 | #' @param w95 a numeric vector, this parameter is used in the [weight_allom()] 22 | #' function to determine the value at which the sample-size-related weight 23 | #' reaches 95% of its maximum value (max=1). Default is 500. 24 | #' @param nres number of resampled values. Default is "1e4". 25 | #' 26 | #' @return An object of class "data.frame" of resampled DBHs and associated AGB 27 | #' from the equation table; the number of resampled DBHs is proportional to 28 | #' the weight provided by the [weight_allom()] function. 29 | #' 30 | #' @seealso [weight_allom()], [new_equations()]. 31 | #' 32 | #' @export 33 | #' 34 | #' @examples 35 | #' resample_agb( 36 | #' genus = "Quercus", 37 | #' species = "rubra", 38 | #' coords = c(-78.2, 38.9) 39 | #' ) 40 | resample_agb <- function(genus, 41 | coords, 42 | species = NULL, 43 | new_eqtable = NULL, 44 | wna = 0.1, 45 | w95 = 500, 46 | nres = 1e4) { 47 | if (length(genus) > 1 | length(unlist(coords)) != 2) { 48 | abort("`genus` must hold a single taxon, and `coords` a single location.") 49 | } 50 | 51 | if (!is.null(new_eqtable)) { 52 | dfequation <- new_eqtable 53 | } else { 54 | dfequation <- new_equations() 55 | } 56 | 57 | weights <- weight_allom( 58 | genus = genus, 59 | species = species, 60 | coords = coords, 61 | new_eqtable = dfequation, 62 | wna = wna, 63 | w95 = w95 64 | ) 65 | weights <- data.table::data.table( 66 | weight = weights, 67 | equation_id = names(weights) 68 | ) 69 | if ("weight" %in% colnames(dfequation)) { 70 | dfequation$weight <- NULL 71 | } 72 | dfequation <- merge(dfequation, weights, by = "equation_id") 73 | dfequation$weight <- dfequation$weight / sum(dfequation$weight) 74 | dfequation$resample <- floor(dfequation$weight * nres) 75 | dfsub <- subset(dfequation, resample > 0)[, c( 76 | "dbh_min_cm", 77 | "dbh_max_cm", 78 | "resample", 79 | "equation_id", 80 | "equation_allometry", 81 | "dbh_unit_cf", 82 | "output_units_cf", 83 | "equation_taxa" 84 | )] 85 | dfsub$dbh_min_cm[is.na(dfsub$dbh_min_cm)] <- 1 86 | dfsub$dbh_max_cm[is.na(dfsub$dbh_max_cm)] <- 200 87 | list_dbh <- apply(dfsub[, 1:3], 1, function(x) { 88 | withr::with_seed(40, stats::runif(x[3], x[1], x[2])) 89 | }) 90 | 91 | ## if possible, introduce some randomness 92 | ## when we have some information from the allometry: use it, 93 | ## otherwise use a conservative sigma 94 | if (nrow(dfsub) == 1) { 95 | ## only 1 equation selected 96 | list_dbh <- c(list_dbh) 97 | sampled_dbh <- list_dbh 98 | orig_equation <- dfsub$equation_allometry 99 | new_dbh <- paste0("(sampled_dbh * ", dfsub$dbh_unit_cf, ")") 100 | new_equation <- gsub("dbh|DBH", new_dbh, orig_equation) 101 | list_agb <- 102 | eval(parse(text = new_equation)) * dfsub$output_units_cf 103 | } else { 104 | list_agb <- lapply(seq_len(length(list_dbh)), function(j) { 105 | sampled_dbh <- list_dbh[[j]] 106 | orig_equation <- dfsub$equation_allometry[j] 107 | new_dbh <- paste0("(sampled_dbh * ", dfsub$dbh_unit_cf[j], ")") 108 | new_equation <- gsub("dbh|DBH", new_dbh, orig_equation) 109 | agb <- 110 | eval(parse(text = new_equation)) * dfsub$output_units_cf[j] 111 | }) 112 | } 113 | 114 | equation_id <- 115 | unlist(lapply(seq_len(nrow(dfsub)), function(i) { 116 | rep(dfsub$equation_id[i], each = dfsub$resample[i]) 117 | })) 118 | 119 | df <- tibble::tibble(equation_id, 120 | dbh = unlist(list_dbh), 121 | agb = unlist(list_agb) 122 | ) 123 | return(df) 124 | } 125 | -------------------------------------------------------------------------------- /R/sysdata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/R/sysdata.rda -------------------------------------------------------------------------------- /R/validate_equation.R: -------------------------------------------------------------------------------- 1 | #' Validate equations 2 | #' 3 | #' @param equations A character vector giving equations to validate. 4 | #' @param dbh,h Independent variables. 5 | #' @param env An environment on which to evaluate the equations. 6 | #' 7 | #' @return This function is called for its side effect of throwing an error if 8 | #' at least one equation is invalid. Valid equations are returned invisibly. 9 | #' 10 | #' @examples 11 | #' # Good 12 | #' validate_one_equation("dbh + 1") 13 | #' 14 | #' # Fails 15 | #' try(validate_one_equation("bad + 1")) 16 | #' 17 | #' equations <- allodb::equations$equation_allometry 18 | #' try(validate_equations(equations)) 19 | #' 20 | #' # FIXME: Some equations use "DBH" in uppercase. Is this intentional? 21 | #' grep("DBH", equations, value = TRUE)[[1]] # But we also have uppercase 22 | #' grep("dbh", equations, value = TRUE)[[1]] # I expected only lowercase 23 | #' valid <- tolower(equations) 24 | #' 25 | #' try(validate_equations(valid)) 26 | #' @noRd 27 | validate_equations <- function(equations, dbh = 1, h = 1, env = current_env()) { 28 | walk_apply(equations, validate_one_equation, dbh = dbh, h = h, env = env) 29 | } 30 | 31 | validate_one_equation <- function(equation, dbh = 1, h = 1, env = current_env()) { 32 | tryCatch( 33 | eval(parse(text = equation), envir = env), 34 | error = function(e) { 35 | abort(c( 36 | "`text` must be valid R code.", 37 | x = paste("Invalid:", equation), 38 | x = paste("Error:", conditionMessage(e)) 39 | )) 40 | } 41 | ) 42 | 43 | invisible(equation) 44 | } 45 | 46 | current_env <- function() { 47 | parent.frame() 48 | } 49 | 50 | # Like purrr::walk() 51 | walk_apply <- function(.x, .f, ...) { 52 | lapply(.x, .f, ...) 53 | invisible(.x) 54 | } 55 | -------------------------------------------------------------------------------- /R/weight_allom.R: -------------------------------------------------------------------------------- 1 | #' Attribute weights to equations 2 | #' 3 | #' This function attributes a weight to each equation based on its sampling 4 | #' size, and taxonomic and climatic similarity with the species/site combination 5 | #' considered. 6 | #' 7 | #' Each equation is given a weight by the function [weight_allom()], calculated 8 | #' as the product of the following components: 9 | #' 10 | #' (1) sample-size weight, calculated as: 11 | #' 12 | #' \deqn{1-exp(-n*(log(20)/w95))} 13 | #' 14 | #' where n is the sample size of the equation; the weight given to equations 15 | #' with no sample size information is determined by argument `wna` (0.1 by 16 | #' default). 17 | #' 18 | #' (2) climate weight, based on the similarity between the climatic conditions 19 | #' of the equation site and the target location, using the three-letter system 20 | #' of Koppen's climate scheme. Climate weights associated with each combination 21 | #' of two Koppen climates are provided in `data("koppenMatrix")`. The resulting 22 | #' weight has a value between 1e-6 (different climate groups) and 1 (exactly the 23 | #' same climate classification). When an equation was calibrated with trees from 24 | #' several locations with different Koppen climates, the maximum value out of 25 | #' all pairwise equation-site climate weights is used. 26 | #' 27 | #' (3) taxonomic weight: equal to 1 for same species equations, 0.8 for same 28 | #' genus equations, 0.5 for same family equations and for equations calibrated 29 | #' for the same broad functional or taxonomic group (e.g. shrubs, conifers, 30 | #' angiosperms). All other equations are given a low taxonomic weight of 1e-6: 31 | #' these equations will have a significant relative weight in the final 32 | #' prediction only when no other more specific equation is available. 33 | #' 34 | #' @param genus a character value, containing the genus (e.g. "Quercus") of the 35 | #' tree. 36 | #' @param coords a numeric vector of length 2 with longitude and latitude. 37 | #' @param species a character vector (same length as genus), containing the 38 | #' species (e.g. "rubra") of the tree. Default is `NULL`, when no species 39 | #' identification is available. 40 | #' @param new_eqtable Optional. An equation table created with the 41 | #' [new_equations()] function. 42 | #' @param wna a numeric vector, this parameter is used in the [weight_allom()] 43 | #' function to determine the sample-size related weights attributed to 44 | #' equations without a specified sample size. Default is 0.1. 45 | #' @param w95 a numeric vector, this parameter is used to determine the value at 46 | #' which the sample-size-related weight reaches 95% of its maximum value 47 | #' (max=1). Default is 500. 48 | #' 49 | #' @return A named "numeric" vector with one weight for each equation. 50 | #' 51 | #' @seealso [get_biomass()], [new_equations()]. 52 | #' 53 | #' @export 54 | #' 55 | #' @examples 56 | #' x <- weight_allom( 57 | #' genus = "Acer", 58 | #' species = "negundo", 59 | #' coords = c(-78.2, 38.9) 60 | #' ) 61 | #' str(x) 62 | #' head(x) 63 | weight_allom <- function(genus, 64 | coords, 65 | species = NULL, 66 | new_eqtable = NULL, 67 | wna = 0.1, 68 | w95 = 500) { 69 | if (!is.null(new_eqtable)) { 70 | dfequation <- new_eqtable 71 | } else { 72 | dfequation <- new_equations() 73 | } 74 | 75 | ### sample size weight #### 76 | b <- log(20) / w95 77 | suppressWarnings(dfequation$wn <- 78 | (1 - exp( 79 | -b * as.numeric(dfequation$sample_size) 80 | ))) 81 | dfequation$wn[is.na(dfequation$wn)] <- wna 82 | 83 | ### climate weight #### 84 | # (1) get koppen climate 85 | coords_site <- t(as.numeric(coords)) 86 | rcoords_site <- round(coords_site * 2 - 0.5) / 2 + 0.25 87 | ## extract koppen climate of every location 88 | koppen_obs <- apply(rcoords_site, 1, function(xk) { 89 | subset(climatezones, Lon == xk[1] & Lat == xk[2])$Cls 90 | }) 91 | if (length(koppen_obs) == 0) { 92 | warning( 93 | "The coordinates c(", 94 | paste(coords, collapse = ","), 95 | ") are not associated with a Koppen climate zone." 96 | ) 97 | dfequation$we <- 1e-6 98 | } else { 99 | kopmatrix <- subset(allodb::koppenMatrix, zone1 == koppen_obs) 100 | compare_koppen <- function(kopp) { 101 | kopp <- tolower(unlist(strsplit(kopp, ", |; |,|;"))) 102 | max(subset(kopmatrix, tolower(zone2) %in% kopp)$we) 103 | } 104 | dfequation$we <- vapply(dfequation$koppen, compare_koppen, FUN.VALUE = 0.9) 105 | ## error message when the koppen climate of the site does not correspond to 106 | ## any equation 107 | if (sum(dfequation$we) < 0.2) { 108 | warning(paste0( 109 | "The Koppen climate zone corresponding to coordinates (", 110 | paste(coords, collapse = ", "), 111 | ") is ", 112 | koppen_obs, 113 | " and is not represented in your equation table." 114 | )) 115 | } 116 | } 117 | 118 | 119 | ### taxo weight #### 120 | ## 'clean' equation taxa column and separate several taxa all character 121 | ## strings to lower cases to avoid inconsistencies 122 | dfequation$equation_taxa <- tolower(dfequation$equation_taxa) 123 | ## remove " sp." from genus in equation taxa 124 | dfequation$equation_taxa <- 125 | gsub(" sp//.", "", dfequation$equation_taxa) 126 | ## split by "/" when there are several species or families 127 | taxa <- 128 | data.table::tstrsplit(dfequation$equation_taxa, "/| / | /|/ ") 129 | taxa <- do.call(cbind, taxa) 130 | colnames(taxa) <- paste0("taxa", seq_len(ncol(taxa))) 131 | dfequation <- cbind(dfequation, taxa) 132 | ## get family of input genus 133 | genus_obs <- tolower(genus) 134 | genus_family <- 135 | subset(allodb::genus_family, tolower(genus) == genus_obs) 136 | family_obs <- tolower(genus_family$family) 137 | 138 | ## basic weight = 1e-6 (equations used only if no other is available) 139 | dfequation$wt <- 1e-6 140 | 141 | # same genus 142 | dfequation$wt[dfequation$taxa1 == genus_obs] <- 0.8 143 | # same genus, different species 144 | eqtaxa_g <- data.table::tstrsplit(dfequation$taxa1, " ")[[1]] 145 | eqtaxa_s <- data.table::tstrsplit(dfequation$taxa1, " ")[[2]] 146 | dfequation$wt[eqtaxa_g == genus_obs & !is.na(eqtaxa_s)] <- 0.7 147 | # same species 148 | dfequation$wt[dfequation$taxa1 == paste(genus_obs, species) | 149 | (dfequation$taxa2 == paste(genus_obs, species) & 150 | !is.na(dfequation$taxa2))] <- 1 151 | # # same family 152 | dfequation$wt[dfequation$taxa1 == family_obs | 153 | (!is.na(dfequation$taxa2) & 154 | dfequation$taxa2 == family_obs) | 155 | (!is.na(dfequation$taxa3) & 156 | dfequation$taxa3 == family_obs) | 157 | (!is.na(dfequation$taxa4) & 158 | dfequation$taxa4 == family_obs) | 159 | (!is.na(dfequation$taxa5) & 160 | dfequation$taxa5 == family_obs) | 161 | (!is.na(dfequation$taxa6) & 162 | dfequation$taxa6 == family_obs)] <- 0.5 163 | # generic equations 164 | ## conifers / gymnosperms? 165 | conifers <- allodb::gymno_genus$Genus[allodb::gymno_genus$conifer] 166 | # yes 167 | dfequation$wt[genus_obs %in% conifers & 168 | dfequation$equation_taxa == "conifers"] <- 0.3 169 | # no 170 | dfequation$wt[!(genus_obs %in% allodb::gymno_genus$Genus) & 171 | dfequation$equation_taxa == "broad-leaved species"] <- 172 | 0.3 173 | ## tree or shrub? 174 | shrub_genus <- 175 | gsub( 176 | " sp\\.", 177 | "", 178 | grep(" sp\\.", allodb::shrub_species, value = TRUE) 179 | ) 180 | # shrubs (all) 181 | dfequation$wt[(paste(genus_obs, species) %in% allodb::shrub_species | 182 | genus_obs %in% shrub_genus) & 183 | dfequation$equation_taxa == "shrubs"] <- 0.3 184 | # shrubs (angio) 185 | dfequation$wt[(paste(genus_obs, species) %in% allodb::shrub_species | 186 | genus_obs %in% shrub_genus) & 187 | !(genus_obs %in% allodb::gymno_genus$Genus) & 188 | dfequation$equation_taxa == "shrubs (angiosperms)"] <- 189 | 0.3 190 | # trees (all) 191 | dfequation$wt[!paste(genus_obs, species) %in% allodb::shrub_species & 192 | !genus_obs %in% shrub_genus & 193 | dfequation$equation_taxa == "trees 194 | (angiosperms/gymnosperms)"] <- 195 | 0.3 196 | # trees (angio) 197 | dfequation$wt[!paste(genus_obs, species) %in% allodb::shrub_species & 198 | !genus_obs %in% shrub_genus & 199 | !(genus_obs %in% allodb::gymno_genus$Genus) & 200 | dfequation$equation_taxa == "trees (angiosperms)"] <- 201 | 0.3 202 | 203 | ### final weights #### 204 | # multiplicative weights: if one is zero, the total weight should be zero too 205 | dfequation$w <- dfequation$wn * dfequation$we * dfequation$wt 206 | 207 | vec_w <- dfequation$w 208 | names(vec_w) <- dfequation$equation_id 209 | return(vec_w) 210 | } 211 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | fig.width = 6, 13 | fig.height = 5 14 | ) 15 | ``` 16 | 17 | # allodb: An R package for biomass estimation at extratropical forest plots 18 | 19 | 20 | [![peer-review](https://badges.ropensci.org/436_status.svg)](https://github.com/ropensci/software-review/issues/436) 21 | [![Codecov test coverage](https://codecov.io/gh/ropensci/allodb/branch/master/graph/badge.svg)](https://app.codecov.io/gh/ropensci/allodb?branch=master) 22 | [![R-CMD-check](https://github.com/ropensci/allodb/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/allodb/actions) 23 | [![R-CMD-check](https://github.com/ropensci/allodb/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/allodb/actions/workflows/R-CMD-check.yaml) 24 | [![Codecov test coverage](https://codecov.io/gh/ropensci/allodb/graph/badge.svg)](https://app.codecov.io/gh/ropensci/allodb) 25 | 26 | 27 | ## Introduction 28 | 29 | Allometric equations for calculation of tree aboveground biomass (AGB) form the basis for estimates of forest carbon storage and exchange with the atmosphere. While standard models exist to calculate forest biomass across the tropics, we lack a standardized tool for computing AGB across the global extratropics. 30 | 31 | _allodb_ was conceived as a framework to standardize and simplify the biomass estimation process across globally distributed extratropical forests (mainly temperate and boreal forests). 32 | With _allodb_ we aimed to: a) compile relevant published and unpublished allometries, focusing on AGB but structured to handle other variables (e.g., height); b) objectively select and integrate appropriate available equations across the full range of tree sizes; and c) serve as a platform for future updates and expansion to other research sites. 33 | 34 | The _allodb_ package contains a dataset of systematically selected published allometric equations. This dataset was built based on 701 woody species identified at 24 large [ForestGEO forest dynamic plots](https://forestgeo.si.edu/) representing all major extratropical forest types. A total of 570 parsed allometric equations to estimate individual tree biomass were retrieved, checked, and combined using a weighting function designed to ensure optimal equation selection over the full tree size range with smooth transitions across equations. The equation dataset used can be customized with built-in functions that subset the original dataset and add new equations. 35 | 36 | The package provides functions to estimate tree biomass based on user-provided census data (tree diameter, taxonomic identification, and plot coordinates). New allometric equations are calibrated for each species and location by resampling the original equations; equations with a larger sample size and/or higher taxonomic and climatic similarity with the species and location in question are given a higher weight in this process. 37 | 38 | ## Installation 39 | 40 | Install the development version of _allodb_ from GitHub: 41 | 42 | ```R 43 | # install.packages("pak") 44 | pak::pak("ropensci/allodb") 45 | ``` 46 | 47 | ## Examples 48 | 49 | Prior to calculating tree biomass using _allodb_, users need to provide a table (i.e. dataframe) with DBH (cm), parsed species Latin names, and site(s) coordinates. In the following examples we use data from the Smithsonian Conservation Biology Institute, USA (SCBI) ForestGEO dynamics plot (trees from 1 hectare surveyed in 2008). Full tree census data can be requested through the [ForestGEO portal](https://forestgeo.si.edu/explore-data). 50 | 51 | ```{r open-data} 52 | library(allodb) 53 | data(scbi_stem1) 54 | ``` 55 | 56 | The biomass of all trees in one (or several) censuses can be estimated using the `get_biomass` function. 57 | 58 | ```{r calc-agb-all} 59 | scbi_stem1$agb <- 60 | get_biomass( 61 | dbh = scbi_stem1$dbh, 62 | genus = scbi_stem1$genus, 63 | species = scbi_stem1$species, 64 | coords = c(-78.2, 38.9) 65 | ) 66 | ``` 67 | 68 | Biomass for a single tree can be estimated given dbh and species identification (results in kilograms). 69 | 70 | ```{r calc-agb-poplar} 71 | get_biomass( 72 | dbh = 50, 73 | genus = "liriodendron", 74 | species = "tulipifera", 75 | coords = c(-78.2, 38.9) 76 | ) 77 | ``` 78 | 79 | Users can modify the set of equations that will be used to estimate the biomass using the `new_equations` function. The default option is the entire _allodb_ equation table. Users can also work on a subset of those equations, or add new equations to the table (see `?allodb::new_equations`). This new equation table should be provided as an argument in the `get_biomass` function. 80 | 81 | ```{r} 82 | show_cols <- c("equation_id", "equation_taxa", "equation_allometry") 83 | eq_tab_acer <- new_equations(subset_taxa = "Acer") 84 | head(eq_tab_acer[, show_cols]) 85 | ``` 86 | 87 | Within the `get_biomass` function, this equation table is used to calibrate a new allometric equation for all species/site combinations in the user-provided dataframe. This is done by attributing a weight to each equation based on its sampling size, and taxonomic and climatic similarity with the species/site combination considered. 88 | 89 | ```{r weights} 90 | allom_weights <- 91 | weight_allom( 92 | genus = "Acer", 93 | species = "rubrum", 94 | coords = c(-78, 38) 95 | ) 96 | 97 | ## visualize weights 98 | equ_tab_acer <- new_equations() 99 | equ_tab_acer$weights <- allom_weights 100 | keep_cols <- 101 | c( 102 | "equation_id", 103 | "equation_taxa", 104 | "sample_size", 105 | "weights" 106 | ) 107 | order_weights <- order(equ_tab_acer$weights, decreasing = TRUE) 108 | equ_tab_acer <- equ_tab_acer[order_weights, keep_cols] 109 | head(equ_tab_acer) 110 | ``` 111 | 112 | Equations are then resampled within their original DBH range: the number of resampled values for each equation is proportional to its weight (as attributed by the `weight_allom` function). 113 | 114 | ```{r resample-acer, eval = TRUE} 115 | df_resample <- 116 | resample_agb( 117 | genus = "Acer", 118 | species = "rubrum", 119 | coords = c(-78, 38) 120 | ) 121 | 122 | plot( 123 | df_resample$dbh, 124 | df_resample$agb, 125 | xlab = "DBH (cm)", 126 | ylab = "Resampled AGB values (kg)" 127 | ) 128 | ``` 129 | 130 | 131 | The resampled values are then used to fit the following nonlinear model: , with i.i.d. . The parameters (_a_, _b_, and _sigma_) are returned by the `est_params()` function. 132 | 133 | The resampled values (dots) and new fitted equation (red dotted line) can be visualized with the `illustrate_allodb()` function. 134 | 135 | ```{r est-params-acer, eval = TRUE, fig.height=4, fig.width=10} 136 | pars_acer <- est_params( 137 | genus = "Acer", 138 | species = "rubrum", 139 | coords = c(-78, 38) 140 | ) 141 | illustrate_allodb( 142 | genus = "Acer", 143 | species = "rubrum", 144 | coords = c(-78, 38) 145 | ) 146 | ``` 147 | 148 | 149 | The `est_params` function can be used for all species/site combinations in the dataset at once. 150 | 151 | ```{r est-params-all, eval = TRUE} 152 | params <- est_params( 153 | genus = scbi_stem1$genus, 154 | species = scbi_stem1$species, 155 | coords = c(-78.2, 38.9) 156 | ) 157 | head(params) 158 | ``` 159 | 160 | AGB is then recalculated as `agb = a * dbh^b` within the `get_biomass` function. 161 | 162 | Please note that this package is released with a [Contributor 163 | Code of Conduct](https://ropensci.org/code-of-conduct/). 164 | By contributing to this project, you agree to abide by its terms. 165 | 166 | ## Contributors 167 | 168 | 169 | 170 | 171 | 172 | 173 | All contributions to this project are gratefully acknowledged using the [`allcontributors` package](https://github.com/ropensci/allcontributors) following the [all-contributors](https://allcontributors.org) specification. Contributions of any kind are welcome! 174 | 175 | ### Code 176 | 177 | 178 | 179 | 180 | 186 | 192 | 198 | 204 | 210 | 211 | 212 |
181 | 182 | 183 |
184 | gonzalezeb 185 |
187 | 188 | 189 |
190 | maurolepore 191 |
193 | 194 | 195 |
196 | cpiponiot 197 |
199 | 200 | 201 |
202 | teixeirak 203 |
205 | 206 | 207 |
208 | jeroen 209 |
213 | 214 | 215 | ### Issue Authors 216 | 217 | 218 | 219 | 220 | 226 | 232 | 238 | 239 | 240 |
221 | 222 | 223 |
224 | ValentineHerr 225 |
227 | 228 | 229 |
230 | adamhsparks 231 |
233 | 234 | 235 |
236 | lucas-johnson 237 |
241 | 242 | 243 | ### Issue Contributors 244 | 245 | 246 | 247 | 248 | 254 | 260 | 266 | 272 | 278 | 279 | 280 |
249 | 250 | 251 |
252 | ErvanCH 253 |
255 | 256 | 257 |
258 | laosuz 259 |
261 | 262 | 263 |
264 | tylerlittlefield 265 |
267 | 268 | 269 |
270 | rudeboybert 271 |
273 | 274 | 275 |
276 | tlbeckham 277 |
281 | 282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # allodb: An R package for biomass estimation at extratropical forest plots 6 | 7 | 8 | 9 | [![peer-review](https://badges.ropensci.org/436_status.svg)](https://github.com/ropensci/software-review/issues/436) 10 | [![Codecov test 11 | coverage](https://codecov.io/gh/ropensci/allodb/branch/master/graph/badge.svg)](https://app.codecov.io/gh/ropensci/allodb?branch=master) 12 | [![R-CMD-check](https://github.com/ropensci/allodb/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/allodb/actions) 13 | [![R-CMD-check](https://github.com/ropensci/allodb/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/allodb/actions/workflows/R-CMD-check.yaml) 14 | [![Codecov test 15 | coverage](https://codecov.io/gh/ropensci/allodb/graph/badge.svg)](https://app.codecov.io/gh/ropensci/allodb) 16 | 17 | 18 | ## Introduction 19 | 20 | Allometric equations for calculation of tree aboveground biomass (AGB) 21 | form the basis for estimates of forest carbon storage and exchange with 22 | the atmosphere. While standard models exist to calculate forest biomass 23 | across the tropics, we lack a standardized tool for computing AGB across 24 | the global extratropics. 25 | 26 | *allodb* was conceived as a framework to standardize and simplify the 27 | biomass estimation process across globally distributed extratropical 28 | forests (mainly temperate and boreal forests). With *allodb* we aimed 29 | to: a) compile relevant published and unpublished allometries, focusing 30 | on AGB but structured to handle other variables (e.g., height); b) 31 | objectively select and integrate appropriate available equations across 32 | the full range of tree sizes; and c) serve as a platform for future 33 | updates and expansion to other research sites. 34 | 35 | The *allodb* package contains a dataset of systematically selected 36 | published allometric equations. This dataset was built based on 701 37 | woody species identified at 24 large [ForestGEO forest dynamic 38 | plots](https://forestgeo.si.edu/) representing all major extratropical 39 | forest types. A total of 570 parsed allometric equations to estimate 40 | individual tree *dry* biomass were retrieved, checked, and combined using a 41 | weighting function designed to ensure optimal equation selection over 42 | the full tree size range with smooth transitions across equations. The 43 | equation dataset used can be customized with built-in functions that 44 | subset the original dataset and add new equations. 45 | 46 | The package provides functions to estimate tree biomass (dry) based on 47 | user-provided census data (tree diameter, taxonomic identification, and 48 | plot coordinates). New allometric equations are calibrated for each 49 | species and location by resampling the original equations; equations 50 | with a larger sample size and/or higher taxonomic and climatic 51 | similarity with the species and location in question are given a higher 52 | weight in this process. 53 | 54 | ## Installation 55 | 56 | Install the development version of *allodb* from GitHub: 57 | 58 | ``` r 59 | # install.packages("pak") 60 | pak::pak("ropensci/allodb") 61 | ``` 62 | 63 | ## Examples 64 | 65 | Prior to calculating tree biomass using *allodb*, users need to provide 66 | a table (i.e. dataframe) with DBH (cm), parsed species Latin names, and 67 | site(s) coordinates. In the following examples we use data from the 68 | Smithsonian Conservation Biology Institute, USA (SCBI) ForestGEO 69 | dynamics plot (trees from 1 hectare surveyed in 2008). Full tree census 70 | data can be requested through the [ForestGEO 71 | portal](https://forestgeo.si.edu/explore-data). 72 | 73 | ``` r 74 | library(allodb) 75 | data(scbi_stem1) 76 | ``` 77 | 78 | The biomass of all trees in one (or several) censuses can be estimated 79 | using the `get_biomass` function. 80 | 81 | ``` r 82 | scbi_stem1$agb <- 83 | get_biomass( 84 | dbh = scbi_stem1$dbh, 85 | genus = scbi_stem1$genus, 86 | species = scbi_stem1$species, 87 | coords = c(-78.2, 38.9) 88 | ) 89 | ``` 90 | 91 | Biomass for a single tree can be estimated given dbh and species 92 | identification (results in kilograms dry biomass). 93 | 94 | ``` r 95 | get_biomass( 96 | dbh = 50, 97 | genus = "liriodendron", 98 | species = "tulipifera", 99 | coords = c(-78.2, 38.9) 100 | ) 101 | #> [1] 1578.644 102 | ``` 103 | 104 | Users can modify the set of equations that will be used to estimate the 105 | biomass using the `new_equations` function. The default option is the 106 | entire *allodb* equation table. Users can also work on a subset of those 107 | equations, or add new equations to the table (see 108 | `?allodb::new_equations`). This new equation table should be provided as 109 | an argument in the `get_biomass` function. 110 | 111 | ``` r 112 | show_cols <- c("equation_id", "equation_taxa", "equation_allometry") 113 | eq_tab_acer <- new_equations(subset_taxa = "Acer") 114 | head(eq_tab_acer[, show_cols]) 115 | #> # A tibble: 6 × 3 116 | #> equation_id equation_taxa equation_allometry 117 | #> 118 | #> 1 a4e4d1 Acer saccharum exp(-2.192-0.011*dbh+2.67*(log(dbh))) 119 | #> 2 dfc2c7 Acer rubrum 2.02338*(dbh^2)^1.27612 120 | #> 3 eac63e Acer rubrum 5.2879*(dbh^2)^1.07581 121 | #> 4 f49bcb Acer pseudoplatanus exp(-5.644074+(2.5189*(log(pi*dbh)))) 122 | #> 5 14bf3d Acer mandshuricum 0.0335*(dbh)^1.606+0.0026*(dbh)^3.323+0.1222*… 123 | #> 6 0c7cd6 Acer mono 0.0202*(dbh)^1.810+0.0111*(dbh)^2.740+0.1156*… 124 | ``` 125 | 126 | Within the `get_biomass` function, this equation table is used to 127 | calibrate a new allometric equation for all species/site combinations in 128 | the user-provided dataframe. This is done by attributing a weight to 129 | each equation based on its sampling size, and taxonomic and climatic 130 | similarity with the species/site combination considered. 131 | 132 | ``` r 133 | allom_weights <- 134 | weight_allom( 135 | genus = "Acer", 136 | species = "rubrum", 137 | coords = c(-78, 38) 138 | ) 139 | 140 | ## visualize weights 141 | equ_tab_acer <- new_equations() 142 | equ_tab_acer$weights <- allom_weights 143 | keep_cols <- 144 | c( 145 | "equation_id", 146 | "equation_taxa", 147 | "sample_size", 148 | "weights" 149 | ) 150 | order_weights <- order(equ_tab_acer$weights, decreasing = TRUE) 151 | equ_tab_acer <- equ_tab_acer[order_weights, keep_cols] 152 | head(equ_tab_acer) 153 | #> # A tibble: 6 × 4 154 | #> equation_id equation_taxa sample_size weights 155 | #> 156 | #> 1 138258 Acer rubrum 150 0.415 157 | #> 2 d6be5c Sapindaceae 243 0.383 158 | #> 3 a2fbbb Sapindaceae 200 0.349 159 | #> 4 2630d5 Trees (Angiosperms) 886 0.299 160 | #> 5 d4c590 Trees (Angiosperms) 549 0.289 161 | #> 6 ed748f Broad-leaved species 2223 0.270 162 | ``` 163 | 164 | Equations are then resampled within their original DBH range: the number 165 | of resampled values for each equation is proportional to its weight (as 166 | attributed by the `weight_allom` function). 167 | 168 | ``` r 169 | df_resample <- 170 | resample_agb( 171 | genus = "Acer", 172 | species = "rubrum", 173 | coords = c(-78, 38) 174 | ) 175 | 176 | plot( 177 | df_resample$dbh, 178 | df_resample$agb, 179 | xlab = "DBH (cm)", 180 | ylab = "Resampled AGB values (kg)" 181 | ) 182 | ``` 183 | 184 | ![](man/figures/README-resample-acer-1.png) 185 | 186 | The resampled values are then used to fit the following nonlinear model: 187 | , 188 | with i.i.d. 189 | . 190 | The parameters (*a*, *b*, and *sigma*) are returned by the 191 | `est_params()` function. 192 | 193 | The resampled values (dots) and new fitted equation (red dotted line) 194 | can be visualized with the `illustrate_allodb()` function. 195 | 196 | ``` r 197 | pars_acer <- est_params( 198 | genus = "Acer", 199 | species = "rubrum", 200 | coords = c(-78, 38) 201 | ) 202 | illustrate_allodb( 203 | genus = "Acer", 204 | species = "rubrum", 205 | coords = c(-78, 38) 206 | ) 207 | ``` 208 | 209 | ![](man/figures/README-est-params-acer-1.png) 210 | 211 | The `est_params` function can be used for all species/site combinations 212 | in the dataset at once. 213 | 214 | ``` r 215 | params <- est_params( 216 | genus = scbi_stem1$genus, 217 | species = scbi_stem1$species, 218 | coords = c(-78.2, 38.9) 219 | ) 220 | head(params) 221 | #> # A tibble: 6 × 7 222 | #> genus species long lat a b sigma 223 | #> 224 | #> 1 Acer negundo -78.2 38.9 0.0762 2.55 433. 225 | #> 2 Acer rubrum -78.2 38.9 0.0768 2.55 412. 226 | #> 3 Ailanthus altissima -78.2 38.9 0.0995 2.48 377. 227 | #> 4 Amelanchier arborea -78.2 38.9 0.0690 2.56 359. 228 | #> 5 Asimina triloba -78.2 38.9 0.0995 2.48 377. 229 | #> 6 Carpinus caroliniana -78.2 38.9 0.0984 2.48 317. 230 | ``` 231 | 232 | AGB is then recalculated as `agb = a * dbh^b` within the `get_biomass` 233 | function. 234 | 235 | Please note that this package is released with a [Contributor Code of 236 | Conduct](https://ropensci.org/code-of-conduct/). By contributing to this 237 | project, you agree to abide by its terms. 238 | 239 | ## Contributors 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | All contributions to this project are gratefully acknowledged using the 248 | [`allcontributors` package](https://github.com/ropensci/allcontributors) 249 | following the [all-contributors](https://allcontributors.org) 250 | specification. Contributions of any kind are welcome! 251 | 252 | ### Code 253 | 254 | 255 | 256 | 257 | 258 | 265 | 266 | 273 | 274 | 281 | 282 | 289 | 290 | 297 | 298 | 299 | 300 |
259 | 260 | 261 | 262 |
263 | gonzalezeb 264 |
267 | 268 | 269 | 270 |
271 | maurolepore 272 |
275 | 276 | 277 | 278 |
279 | cpiponiot 280 |
283 | 284 | 285 | 286 |
287 | teixeirak 288 |
291 | 292 | 293 | 294 |
295 | jeroen 296 |
301 | 302 | ### Issue Authors 303 | 304 | 305 | 306 | 307 | 308 | 315 | 316 | 323 | 324 | 331 | 332 | 333 | 334 |
309 | 310 | 311 | 312 |
313 | ValentineHerr 314 |
317 | 318 | 319 | 320 |
321 | adamhsparks 322 |
325 | 326 | 327 | 328 |
329 | lucas-johnson 330 |
335 | 336 | ### Issue Contributors 337 | 338 | 339 | 340 | 341 | 342 | 349 | 350 | 357 | 358 | 365 | 366 | 373 | 374 | 381 | 382 | 383 | 384 |
343 | 344 | 345 | 346 |
347 | ErvanCH 348 |
351 | 352 | 353 | 354 |
355 | laosuz 356 |
359 | 360 | 361 | 362 |
363 | tylerlittlefield 364 |
367 | 368 | 369 | 370 |
371 | rudeboybert 372 |
375 | 376 | 377 | 378 |
379 | tlbeckham 380 |
385 | 386 | 387 | 388 | 389 | 390 | 391 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://forestgeo.github.io/allodb 2 | 3 | reference: 4 | - title: Functions 5 | contents: 6 | - -has_concept("database datasets") 7 | - -has_concept("datasets") 8 | 9 | - title: Database datasets 10 | contents: 11 | - has_concept("database datasets") 12 | 13 | - title: Other datasets 14 | contents: 15 | - has_concept("datasets") 16 | -------------------------------------------------------------------------------- /allodb.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace,vignette 22 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | 3 | * ubuntu 18.04 (local), R 4.0.3 4 | * ubuntu 18.04 (github actions), R 3.5, R 3.6, R-oldrel, R-release, R-devel 5 | * macOS-latest (github actions), R-release 6 | * windows-latest (github actions), R 3.6, R-release 7 | * win-builder, R-release, R-devel 8 | 9 | ## R CMD check results 10 | 11 | 0 errors | 0 warnings | 1 note 12 | 13 | * This is a new release. 14 | -------------------------------------------------------------------------------- /data-raw/available_random_ids.csv: -------------------------------------------------------------------------------- 1 | random_id 2 | d408e7 3 | b565f8 4 | c43108 5 | 864fa1 6 | fb70aa 7 | 28d970 8 | d1b8ca 9 | b6e7a5 10 | f9e901 11 | 10a853 12 | 24e611 13 | 3ffae2 14 | f8ec07 15 | 9ac6f0 16 | ec0ea3 17 | 4f3561 18 | 3ca1e9 19 | 81df43 20 | c8e581 21 | ad1e83 22 | ecee5a 23 | 64b114 24 | f6e60d 25 | ded13a 26 | 102f61 27 | b7ee4e 28 | b68a62 29 | 71f38f 30 | cb7039 31 | 68de95 32 | ce2366 33 | 3d4c19 34 | 3bc643 35 | 0f7955 36 | 38b2c5 37 | 951360 38 | 49f982 39 | 19977e 40 | 0e3cac 41 | 1ed135 42 | eaf164 43 | 96f547 44 | 9ac183 45 | 6f7662 46 | 1ac089 47 | 159c57 48 | 62db4a 49 | 4dfece 50 | b95b5e 51 | 0af832 52 | 8745ce 53 | a56149 54 | 459c73 55 | 4d19ab 56 | 06e318 57 | 38adcd 58 | 639a99 59 | b82fbb 60 | 649729 61 | c39ba7 62 | 73397a 63 | 0aca12 64 | 10caf3 65 | 60b903 66 | 64fc17 67 | a2818f 68 | 4430d1 69 | 0cbd73 70 | 817379 71 | 1af349 72 | 485d2e 73 | abb74b 74 | 24dc31 75 | 00baa0 76 | 77c7d3 77 | 3dde1e 78 | 1dddce 79 | 3ef83d 80 | 98499d 81 | 8b0a50 82 | 4b8fdc 83 | af686d 84 | d7949b 85 | 7876cd 86 | db099f 87 | 371c5b 88 | 861d61 89 | cc656e 90 | 33ff5d 91 | 8fdc01 92 | ad8928 93 | fe04bd 94 | 4610f0 95 | 5d78a7 96 | d429c3 97 | 67e555 98 | 7d34df 99 | 6c0624 100 | edfc50 101 | 6ecf6d 102 | 22f41e 103 | 3997b9 104 | a99d6b 105 | ccca94 106 | e898dc 107 | aab983 108 | f1bb6f 109 | 906d2c 110 | 869c88 111 | dd56e7 112 | c82c3b 113 | 9207ee 114 | 11795c 115 | 39cc91 116 | de054d 117 | df9a96 118 | 4e67c4 119 | d858e2 120 | 2880f2 121 | 1af331 122 | bd3f8d 123 | fd4274 124 | dfbb4b 125 | c9ea55 126 | f8a08d 127 | 1eb4a9 128 | 0f5e23 129 | fd55f7 130 | f2366a 131 | 9cd0a5 132 | e821a6 133 | 086c6f 134 | fc0bfa 135 | 45eaa1 136 | d340c4 137 | b1ffec 138 | f4e161 139 | 355dfb 140 | 2799a4 141 | 811f9e 142 | 42f2c3 143 | e4bb59 144 | c4daa9 145 | 4d9dc2 146 | 12c2a0 147 | f8196a 148 | 66dbb1 149 | 79718e 150 | 795505 151 | 62649f 152 | 856587 153 | 9fd853 154 | 48104a 155 | 07f6e5 156 | 8f30a5 157 | 7ce82a 158 | f74ebd 159 | df19f7 160 | 4658b3 161 | 7984c6 162 | cc0577 163 | 711b4e 164 | 113337 165 | 383773 166 | 2cac63 167 | 9c5989 168 | 32da79 169 | b6b9ef 170 | 4deaa6 171 | c73dfa 172 | a52fc2 173 | f4c9b7 174 | 39a751 175 | f08abf 176 | 75aea0 177 | 19c358 178 | ee960f 179 | b72414 180 | a6a8f9 181 | 484dbe 182 | 93c1f8 183 | b43aed 184 | 8e9f36 185 | 24c557 186 | 424e5f 187 | 7b6c71 188 | a32c9a 189 | 38cadc 190 | 5ba68a 191 | a68270 192 | eb8b7f 193 | 708049 194 | e188d0 195 | 9310d8 196 | 38e411 197 | 1bfce6 198 | 004f25 199 | fd95ef 200 | 33664a 201 | 20a193 202 | e9e390 203 | 043cc4 204 | 0eeea9 205 | 1a1b52 206 | 3933ad 207 | 31b6d8 208 | d03755 209 | 41c2b6 210 | 54f9ac 211 | b85c79 212 | e7d26a 213 | 9e5c14 214 | 95196c 215 | 51c1d5 216 | bc859c 217 | 7d1d1a 218 | 2d72a9 219 | 35abc8 220 | 83854 221 | 38230f 222 | d598eb 223 | 4f3338 224 | ca73e5 225 | 988128 226 | 34723e 227 | 613a4b 228 | 10107 229 | 890da3 230 | c9b84d 231 | a4d6c4 232 | 5337be 233 | d059ce 234 | 8f42ea 235 | 4cc4d4 236 | 28304c 237 | d964e1 238 | 3b3904 239 | 5f4d1c 240 | b0ec51 241 | 9f817a 242 | f865b5 243 | 30bb46 244 | 323584 245 | e4e81c 246 | bef8b1 247 | b505e8 248 | 98486 249 | e983f6 250 | 2a230e 251 | d95007 252 | 39fb6b 253 | 1cd78f 254 | 1709d3 255 | 164507 256 | b32c92 257 | 3e5803 258 | 5d2e2e 259 | 4576af 260 | c27523 261 | d738e8 262 | f96874 263 | dc08cd 264 | df2eb0 265 | 192874 266 | 6b02a6 267 | 63430d 268 | 88d234 269 | 1a615c 270 | 18266e 271 | 4ef1f9 272 | 20dd99 273 | ec5d16 274 | 9171a8 275 | 772f26 276 | 753605 277 | 47d737 278 | 64decb 279 | 90de7f 280 | c792e3 281 | 851d58 282 | 7c5a86 283 | 893005 284 | 7df225 285 | 446844 286 | 2af4dd 287 | e5bbc7 288 | 9abb0d 289 | 48daae 290 | ec319a 291 | f86aa3 292 | 8315b8 293 | f9ea28 294 | acb560 295 | 356b55 296 | 61a9b1 297 | 760f5f 298 | dc3af6 299 | 078ba5 300 | b5f3ef 301 | 67d43f 302 | 55156e 303 | 9dabfe 304 | 5.80E+11 305 | cbf469 306 | c82da6 307 | fc9ee2 308 | b45816 309 | 8d6b76 310 | 1ca03e 311 | a34563 312 | 554739 313 | f9b613 314 | 5e5e34 315 | d6d8d6 316 | 76d945 317 | 24023d 318 | 143adf 319 | 380274 320 | c35ce6 321 | 4356ae 322 | 306fc2 323 | 32c77f 324 | 8287de 325 | 98c840 326 | 2262b9 327 | f4427b 328 | 992af5 329 | 7f5f72 330 | d82438 331 | 266c02 332 | 87e541 333 | 4ce784 334 | 6d4ecc 335 | 7af6b1 336 | a15e50 337 | cb36fe 338 | 9b8d83 339 | d7977d 340 | c051b6 341 | 17aa22 342 | 340003 343 | 7bf2dd 344 | 7cb99a 345 | 352832 346 | 6d2261 347 | a1943f 348 | eb2b1f 349 | 01e710 350 | ee0dd4 351 | 3aed4c 352 | 353bfc 353 | e2a077 354 | a7f908 355 | bda4f1 356 | 801d0e 357 | 270578 358 | 2dd712 359 | 09dfe5 360 | fe27cf 361 | efc984 362 | d00224 363 | c57ff4 364 | 4d5541 365 | 6e0d3a 366 | 956193 367 | 1f63ca 368 | 62ea6d 369 | 252e0c 370 | 2abb4f 371 | 82a671 372 | 6ba989 373 | ec1573 374 | 081b5a 375 | 6eac23 376 | 9828a6 377 | 75929b 378 | 925ec8 379 | 426791 380 | 2e5fc4 381 | 2e2e48 382 | 1a29af 383 | fb5952 384 | a40064 385 | f5bdb4 386 | 9dcefc 387 | 6df699 388 | eeac0a 389 | 5ed822 390 | 7a9559 391 | 563d4a 392 | ba3d40 393 | 19f8d9 394 | a49421 395 | 7663ce 396 | 2c02d0 397 | c784c6 398 | 984a65 399 | 3b7262 400 | be0947 401 | 573805 402 | 956fac 403 | 6dc6ee 404 | 3533ac 405 | 7452bb 406 | 682495 407 | 3dc7e2 408 | d67173 409 | 3bfba4 410 | 29ad40 411 | 0c2ec5 412 | c9d6aa 413 | e5200e 414 | 75f7c6 415 | 91fa41 416 | 304fb9 417 | af4db2 418 | 065f41 419 | a42980 420 | 65527a 421 | f98abc 422 | ed1487 423 | 35622e 424 | 5273f2 425 | fe6171 426 | 55fb06 427 | 92710e 428 | 457a30 429 | 4ecfa6 430 | a9a33d 431 | d63bab 432 | 837f98 433 | 356712 434 | 9731d6 435 | 698168 436 | 4b2b96 437 | 3a5bd5 438 | 721587 439 | 4a9470 440 | 3ab2c0 441 | d4d09e 442 | 0d059b 443 | cc7fc5 444 | c6a95e 445 | 826813 446 | 96a3c2 447 | 170d8a 448 | f6a1c7 449 | 76b8c1 450 | ca9ffd 451 | 91df0b 452 | 45b209 453 | 8f407a 454 | 7.87E+02 455 | 4af0ba 456 | 82ccce 457 | 39b16d 458 | bd5fa0 459 | 360a1b 460 | 9ab0e1 461 | cda6ed 462 | 96a94c 463 | 4a290d 464 | 39fe65 465 | 055a9a 466 | 2786d8 467 | 394eae 468 | 251cdc 469 | 212ea1 470 | 23d1e0 471 | 11deca 472 | 6.74E+15 473 | 96755c 474 | d66165 475 | 55e1ae 476 | ff9cb1 477 | 729f78 478 | dfc478 479 | f97e26 480 | 0f9af3 481 | 4d435e 482 | 123446 483 | e3874b 484 | cf47b2 485 | 90b4af 486 | 0b607b 487 | f6b68d 488 | 859144 489 | 5c5b2b 490 | de6e23 491 | 55a08d 492 | c045fd 493 | e26272 494 | d559a8 495 | 7dafe5 496 | 96315e 497 | c2ad86 498 | f842a7 499 | 48f573 500 | 36fce5 501 | 569b28 502 | 08ea57 503 | 59b109 504 | 28ed70 505 | 5349ba 506 | 17815a 507 | 3c229d 508 | 5a96ab 509 | 8d2f27 510 | 33ac2d 511 | 04f58b 512 | 8a9545 513 | 5f5732 514 | 715961 515 | 1e570d 516 | 846a1b 517 | 6ba5fb 518 | 2bcb20 519 | 025d5a 520 | b23fe9 521 | aea4ba 522 | 5f71d8 523 | bc75c0 524 | 7f3653 525 | 213cdc 526 | 420942 527 | 6c87c0 528 | 41021e 529 | e35d63 530 | 40245f 531 | e29884 532 | dddde3 533 | 860aff 534 | bc6949 535 | 73e1fe 536 | d0716b 537 | 2.76E+100 538 | 91448a 539 | 45442f 540 | 179a80 541 | 134fe6 542 | 690db4 543 | c5a2b8 544 | 1ab038 545 | 6a7eea 546 | 1cc20c 547 | 21023e 548 | aa683d 549 | e033d7 550 | 6540a9 551 | 7cce74 552 | 8af304 553 | 32b64a 554 | 15cc23 555 | 780a35 556 | c7554f 557 | 10e78d 558 | 77d92d 559 | 48c1fd 560 | 6be643 561 | e663f4 562 | f2bca9 563 | 538374 564 | 49f3e5 565 | 3bbe62 566 | bc2706 567 | cddf17 568 | 649a2a 569 | fcc3df 570 | 74fa06 571 | 0cac17 572 | d12e03 573 | 461437 574 | 27627b 575 | 5b3b12 576 | 1abbbd 577 | 6e07ea 578 | ead0a9 579 | cb7ae1 580 | 1695a0 581 | 281826 582 | 17bd7f 583 | 303b91 584 | 33d18a 585 | 1f6b34 586 | b4eff1 587 | 1a40bd 588 | 1629bd 589 | 779d2f 590 | 0d8699 591 | cf676a 592 | f68620 593 | 981780 594 | b4e7e8 595 | 222594 596 | d20710 597 | cf52d2 598 | bc250a 599 | 89332c 600 | aac628 601 | 2aed36 602 | 6048f2 603 | 509f17 604 | d51d9c 605 | 54afb5 606 | 4ffa32 607 | c07877 608 | 0427df 609 | b932d5 610 | 559eb4 611 | c248b3 612 | e9ffc2 613 | 4e7db7 614 | fb4e1b 615 | c9f470 616 | 76791e 617 | 975ead 618 | ea1d5a 619 | 3cf26d 620 | abb07a 621 | 35943a 622 | 3be185 623 | 7a1aa9 624 | 2bded5 625 | 11f2a3 626 | 4e3b92 627 | e39646 628 | 3368a0 629 | a8eb85 630 | ad5378 631 | 126561 632 | 221c52 633 | b49b06 634 | b57ab1 635 | b77462 636 | ba6867 637 | 2b15c8 638 | 149c6a 639 | 547952 640 | 22ab95 641 | dac490 642 | 342b54 643 | 0f398e 644 | f67386 645 | f9733b 646 | 4eb95e 647 | f130f0 648 | 7ad726 649 | 55e679 650 | 38573f 651 | 4.72E+25 652 | f0c2bd 653 | a6c2c6 654 | 2f0846 655 | 47a6a6 656 | 9435ee 657 | 0c7591 658 | 5960cb 659 | 6e57f4 660 | 6f682a 661 | d47bec 662 | bfb2ad 663 | 33785c 664 | aa0844 665 | 03a1d1 666 | 4.74E+49 667 | b3b27b 668 | 3b1738 669 | 10ad11 670 | 7.90E+100 671 | 155539 672 | b1c273 673 | d910b6 674 | c364ef 675 | 42d11c 676 | 95ff83 677 | e562e8 678 | f24b4c 679 | a71342 680 | 4c7376 681 | 51be32 682 | ba5538 683 | 1.73E+08 684 | bc00fb 685 | 40758c 686 | 4390ad 687 | 2d4365 688 | 9e998b 689 | d56bbf 690 | 3d09e4 691 | fe79e6 692 | fa87ca 693 | 5042a6 694 | 9ba7af 695 | e85c89 696 | f57305 697 | 9dfa64 698 | 317215 699 | f24e96 700 | 09a894 701 | f615dc 702 | 32311c 703 | 585388 704 | 99f2d3 705 | 157e7d 706 | 0aff51 707 | 8f7afc 708 | 7.40E+35 709 | 05cf8a 710 | d8087e 711 | 169195 712 | 1d38d7 713 | 2d89d9 714 | 1539b8 715 | 9c9fd0 716 | 88a929 717 | 307e1f 718 | 66c424 719 | 471759 720 | c4629b 721 | a0d957 722 | 1cb805 723 | ffdf5e 724 | fc8e38 725 | 349920 726 | 648e0b 727 | b7bfed 728 | 18171e 729 | f776e1 730 | 4f824f 731 | f81b9d 732 | 357817 733 | 2be337 734 | 9aa6d1 735 | 694eef 736 | 34ba8a 737 | b4a9ff 738 | 1a100a 739 | e185ef 740 | 72ad4b 741 | a0be3d 742 | 4.75E+09 743 | 96ea98 744 | 57ae24 745 | 76b922 746 | 4bda2a 747 | bb040f 748 | 6e5cef 749 | 6d4cd1 750 | cd2e1e 751 | 357dee 752 | 90ef9b 753 | 219d6d 754 | 6ad6c6 755 | 4fd4ae 756 | 26cfe3 757 | 78987f 758 | 5a0ef6 759 | 871f3f 760 | 0d2979 761 | 483768 762 | d93b47 763 | 055a15 764 | a097bb 765 | 51f897 766 | 5ef99c 767 | d74734 768 | ef146b 769 | 43b89f 770 | c20f83 771 | 7ab9e1 772 | 238b5d 773 | 79f58f 774 | 96de29 775 | 65b85e 776 | e75929 777 | da0d8d 778 | d6f06e 779 | b04883 780 | a82917 781 | 462a44 782 | 931edd 783 | 131200 784 | 7b8c04 785 | 3decb3 786 | 470cc1 787 | 16e416 788 | ad06c2 789 | 4ead1d 790 | c18bf6 791 | bc52ca 792 | f82e1e 793 | 6c3078 794 | 993a31 795 | 4f453a 796 | d7801f 797 | 04fd90 798 | e19fb1 799 | 31024c 800 | d73799 801 | de4477 802 | f52c24 803 | 8ed784 804 | 52f600 805 | f42dfd 806 | 184f26 807 | 23e77e 808 | b4d0f4 809 | 6df23f 810 | 62d74e 811 | b2f6dd 812 | 7e8c24 813 | b33625 814 | 44e319 815 | fa89a5 816 | 878191 817 | fc110a 818 | f717dd 819 | 7f8ff4 820 | 820d3e 821 | 60fffd 822 | ff0b97 823 | 22e738 824 | df9c81 825 | 7817eb 826 | a03c72 827 | a134c9 828 | 2f8295 829 | 3ff1d9 830 | 173544 831 | b8b95e 832 | 3aefcf 833 | 2e3535 834 | 0fa80a 835 | 27a70f 836 | cf63c3 837 | b816d2 838 | 53311a 839 | 431947 840 | d15edd 841 | afdbfd 842 | 9b6c18 843 | 0a2853 844 | 7ae8ac 845 | b567a2 846 | e35892 847 | 50e28c 848 | 81c595 849 | 7bb025 850 | 74026f 851 | 3dbe0e 852 | 7fd412 853 | dfcb65 854 | cabe38 855 | a5a406 856 | 1f7055 857 | 285997 858 | 74d6b8 859 | 0fd234 860 | b9db2c 861 | c3b17e 862 | 52586c 863 | 516659 864 | a063b9 865 | a3d21b 866 | 8964fa 867 | f187bb 868 | d039b2 869 | 48f29c 870 | b0871d 871 | c1a48f 872 | 89acab 873 | 9da278 874 | f9544e 875 | 2a2923 876 | 7d4e35 877 | 8ef202 878 | cc3019 879 | 328a84 880 | f16e31 881 | 3b466b 882 | 5069dd 883 | 59017 884 | 527725 885 | 6cafa9 886 | a6673a 887 | 31be7a 888 | ddef51 889 | 45e02f 890 | 3450ca 891 | 3.40E+66 892 | 4ad56a 893 | 50740d 894 | 7f3e18 895 | 7d493e 896 | 20129f 897 | 3833ac 898 | 2406db 899 | df1f41 900 | a5e21c 901 | 915535 902 | 5.13E+25 903 | 0b30f8 904 | 7debdf 905 | 506846 906 | f10e2e 907 | dea0ce 908 | 8b5845 909 | 9cb8fc 910 | 8c8d54 911 | e8325c 912 | 18298 913 | 1a0368 914 | 63e2b5 915 | 681de9 916 | db4f6d 917 | e525f4 918 | 8c3d53 919 | b31d30 920 | 822f27 921 | 334b0c 922 | e9f55e 923 | 298b03 924 | 5f0726 925 | 1df45c 926 | 3c2282 927 | 1d1cee 928 | 805ac0 929 | 0a35ac 930 | 18ec6a 931 | 9f45a4 932 | 5bbe63 933 | 2932fc 934 | 90a501 935 | 20c898 936 | dd9110 937 | c65dca 938 | fe1ba3 939 | f3f5e5 940 | 8f99a1 941 | 7d459a 942 | eb3a29 943 | d5e690 944 | f0e463 945 | 3d66d5 946 | 1e480a 947 | eebb2c 948 | b491c4 949 | 2ed88f 950 | ec2727 951 | bc8c83 952 | 2a9aed 953 | 313b11 954 | 7470eb 955 | 24df67 956 | 773554 957 | 3a13fb 958 | c58398 959 | 762e9f 960 | 469b5d 961 | 484a34 962 | 91fa45 963 | 25127c 964 | 38c324 965 | c67845 966 | b22bb8 967 | 4d260e 968 | e07649 969 | fe7aec 970 | 7b98d9 971 | 3.23E+11 972 | e165db 973 | a7acb8 974 | c31420 975 | df8064 976 | f81d95 977 | 69f8e6 978 | adaff3 979 | 233a7f 980 | 444423 981 | 6f5744 982 | de92ad 983 | 586ef5 984 | b21c08 985 | ac98f6 986 | 301c13 987 | 78a5cd 988 | c2ec08 989 | 5d3f62 990 | c27136 991 | 873d9e 992 | 5a74fc 993 | 9118cd 994 | e25d18 995 | 8eb032 996 | ba7c3e 997 | 9f7352 998 | 63b46c 999 | 52fef8 1000 | 7b7dc5 1001 | 8d8dcb 1002 | 8467ad 1003 | 303655 1004 | 8db2d4 1005 | 365cb8 1006 | e91cee 1007 | 4f4d0c 1008 | 616519 1009 | e55192 1010 | 7591b7 1011 | 586ab1 1012 | 6ac45c 1013 | ba4ada 1014 | 597b6a 1015 | e5eed8 1016 | 49c4b2 1017 | 2005b9 1018 | c775b4 1019 | 5a9d3f 1020 | bcd06c 1021 | b37145 1022 | a8aab9 1023 | aeccfb 1024 | b72ba0 1025 | 7fc3dd 1026 | d936eb 1027 | c98dd5 1028 | 2bfede 1029 | 79eb6b 1030 | e304ed 1031 | 8e5e46 1032 | 4b47f7 1033 | 370f5a 1034 | b2a9a5 1035 | eb786e 1036 | ff2403 1037 | 0d70de 1038 | 17224f 1039 | 6.55E+41 1040 | 03b412 1041 | b1090e 1042 | cc552a 1043 | 4dca0f 1044 | ff0a93 1045 | fc60ca 1046 | b8e592 1047 | 2f38be 1048 | ef85f4 1049 | 90aa38 1050 | ed0653 1051 | 247099 1052 | 20a6c1 1053 | 394009 1054 | 54083c 1055 | 5dc9cc 1056 | 7e33be 1057 | 8e2f38 1058 | 6b3f12 1059 | ed824c 1060 | 16b0ef 1061 | f71e09 1062 | 4c0455 1063 | 3fc746 1064 | 857ede 1065 | 8708ab 1066 | 29feea 1067 | bd1ac4 1068 | e7132b 1069 | 07e5d5 1070 | f41bc8 1071 | c8a930 1072 | df7808 1073 | d77b32 1074 | dde913 1075 | deefef 1076 | e97e15 1077 | 270f96 1078 | 0d1b1f 1079 | 1fc867 1080 | 51beed 1081 | 68abd7 1082 | a80688 1083 | 795ce5 1084 | a91c4f 1085 | 18b62c 1086 | c1c1d2 1087 | d580e7 1088 | e5fa7e 1089 | b4cc17 1090 | 30e874 1091 | c9066f 1092 | ab3824 1093 | 8ec9c0 1094 | d48015 1095 | e9258a 1096 | e89264 1097 | 6405fa 1098 | d267d7 1099 | 2c4979 1100 | 5.70E+65 1101 | a0f7b0 1102 | 542340 1103 | c23b69 1104 | aed921 1105 | 2f6c57 1106 | d8f6f0 1107 | 680642 1108 | b31fb7 1109 | 2f8d7d 1110 | 3f0a58 1111 | 1b5833 1112 | d75a9e 1113 | 1bb6b1 1114 | 07adb8 1115 | 870142 1116 | d45aae 1117 | 91e0f1 1118 | 58a9d6 1119 | 6a8456 1120 | b1094f 1121 | 9cfac7 1122 | f63f9e 1123 | 4584de 1124 | 0f233a 1125 | 4737bc 1126 | ba1556 1127 | c17f3a 1128 | 42dbfe 1129 | e280b0 1130 | 0ee2f7 1131 | b49b68 1132 | 3d7e2b 1133 | 1929b6 1134 | 68da89 1135 | 5cf72f 1136 | ae1fe3 1137 | e71a29 1138 | 2fd61a 1139 | 6c360b 1140 | f1898f 1141 | d646cc 1142 | 17fe64 1143 | ab4561 1144 | f11d16 1145 | d6697b 1146 | af3a7e 1147 | 04b9b8 1148 | bb1c0f 1149 | 3f1a15 1150 | 92614c 1151 | d58b74 1152 | df7caa 1153 | d0ecf9 1154 | a16034 1155 | 6e2ad8 1156 | 6d1c0e 1157 | cc63ce 1158 | 8bf329 1159 | 898915 1160 | 2ce506 1161 | e2db1d 1162 | 3e2890 1163 | 83ba19 1164 | 11a72f 1165 | 1abcbe 1166 | eaa293 1167 | 3cf72d 1168 | ddc91c 1169 | 3a7f94 1170 | 02383f 1171 | 82997 1172 | c61077 1173 | 75b0fa 1174 | 33a366 1175 | 1ce3eb 1176 | 4dd168 1177 | 6ac4fc 1178 | 370bfb 1179 | 0c9dd4 1180 | cde808 1181 | 49c87b 1182 | 108714 1183 | 9877b4 1184 | eaf507 1185 | bf39a5 1186 | 46879e 1187 | 647bbe 1188 | 425587 1189 | ec71c2 1190 | 10cd0f 1191 | 9fb7be 1192 | 987b84 1193 | f7e334 1194 | 890303 1195 | 91e5eb 1196 | 37ebc2 1197 | afa15f 1198 | f628c4 1199 | 19f2a0 1200 | 0924f6 1201 | a9b60e 1202 | c998d7 1203 | 4260a5 1204 | 99360 1205 | 4795da 1206 | c26c44 1207 | 73ed29 1208 | 7fdb8e 1209 | ed20e1 1210 | b8c590 1211 | 0fe684 1212 | 37d177 1213 | 622653 1214 | d93193 1215 | c77cd9 1216 | 252f9a 1217 | 89f852 1218 | 293333 1219 | bf2937 1220 | ef1e6f 1221 | 0246c7 1222 | df32f3 1223 | 17e89b 1224 | e0dea2 1225 | 463998 1226 | 5bf0b6 1227 | ab7099 1228 | 31eea2 1229 | e937b3 1230 | 1.54E+07 1231 | 6fee48 1232 | 2a3c4e 1233 | f6671e 1234 | 1d34d1 1235 | 8df84b 1236 | a3d38c 1237 | b13aee 1238 | 249d7d 1239 | 7057d8 1240 | ce4348 1241 | 26737d 1242 | 6dc0ec 1243 | 4790ee 1244 | e12d0d 1245 | de2b19 1246 | 601aac 1247 | 64f57e 1248 | 08b6ab 1249 | 907537 1250 | a89ba8 1251 | 933d3d 1252 | 81a817 1253 | cb40b3 1254 | 0572a0 1255 | e1ef56 1256 | a34bcc 1257 | a408cd 1258 | f2eb1f 1259 | d82528 1260 | 1d3312 1261 | d53557 1262 | c570a9 1263 | 94e9b7 1264 | 1d6690 1265 | bc65ea 1266 | 592232 1267 | a55980 1268 | f0d8b1 1269 | 5023ec 1270 | 174612 1271 | 4abbaf 1272 | 9695b5 1273 | 26aabf 1274 | fb1d80 1275 | 701a24 1276 | ba3cec 1277 | 6b7127 1278 | da5acf 1279 | 637bc4 1280 | e88a39 1281 | c8833e 1282 | 6321c2 1283 | 6fd9b1 1284 | fb5abd 1285 | e7f8b7 1286 | 38bcdb 1287 | 3c028a 1288 | 9.00E+53 1289 | 25b27c 1290 | 6d83d8 1291 | 65caa0 1292 | 1.33E+04 1293 | 787834 1294 | 0c8d84 1295 | d8f0fa 1296 | a334c8 1297 | 892de7 1298 | 71f40b 1299 | 5a7c36 1300 | 24411d 1301 | 545240 1302 | 37a645 1303 | c0e1f8 1304 | e0d628 1305 | fa182a 1306 | 78a5f8 1307 | 4409f6 1308 | 9431f2 1309 | f1af00 1310 | 7f068e 1311 | aecac7 1312 | 5fdee0 1313 | 81d1d8 1314 | dadb0f 1315 | 6e6a09 1316 | ad1433 1317 | 2d86f2 1318 | 54dfb4 1319 | b8a29b 1320 | 4f79be 1321 | e54cb1 1322 | 02230c 1323 | d7cbfb 1324 | e171c3 1325 | 6c5509 1326 | e6157c 1327 | 293154 1328 | c9f594 1329 | cdac38 1330 | 276928 1331 | 3a5cbb 1332 | 6fe899 1333 | 954d62 1334 | 3056df 1335 | 5212ba 1336 | 7ffcf9 1337 | 7d2069 1338 | c0005d 1339 | f389c9 1340 | e367c4 1341 | d7ad39 1342 | a17706 1343 | 857290 1344 | 3.74E+09 1345 | f11890 1346 | 1393ae 1347 | eef23f 1348 | bd3910 1349 | b781b0 1350 | d5960c 1351 | 510c8b 1352 | 700717 1353 | 4f4bc8 1354 | ca668d 1355 | 41e2e8 1356 | 8d4b87 1357 | 316679 1358 | 6b91e3 1359 | 4a7f6e 1360 | d627ce 1361 | 728440 1362 | 32b00c 1363 | 199483 1364 | 65df70 1365 | 8abee9 1366 | 0de882 1367 | fdd82b 1368 | cb1a88 1369 | 744ddb 1370 | e18905 1371 | d4d013 1372 | 8edb5b 1373 | 3fe244 1374 | 8452fd 1375 | 35cc94 1376 | 4b47b0 1377 | 30f1b5 1378 | 9.80E+173 1379 | e8e7f1 1380 | e12376 1381 | 4289bb 1382 | c640cf 1383 | b38eab 1384 | 291aff 1385 | 61bf3b 1386 | de0abe 1387 | 2.48E+07 1388 | e7dcbd 1389 | f6c851 1390 | f041c9 1391 | d07f53 1392 | e4efab 1393 | b2e4a1 1394 | 0120b5 1395 | c0ee5a 1396 | 64f88c 1397 | c2ca87 1398 | 6ad61a 1399 | 48e14e 1400 | a5efe5 1401 | 2e5a42 1402 | 40a199 1403 | da51f2 1404 | 878a71 1405 | 6abf8a 1406 | 1c23aa 1407 | 74702e 1408 | 626979 1409 | 484777 1410 | 66ffbc 1411 | dc4006 1412 | d550b4 1413 | fc26a8 1414 | 6.22E+66 1415 | a9cae4 1416 | fee276 1417 | 93cca5 1418 | 1b760d 1419 | 732f22 1420 | 45056a 1421 | 622dcd 1422 | d47201 1423 | c3b05f 1424 | b9257a 1425 | 5a939b 1426 | 8bd734 1427 | 9.13E+10 1428 | 8c00b0 1429 | d861ef 1430 | 413603 1431 | 102d71 1432 | 02f9fd 1433 | c6670d 1434 | 572453 1435 | 64a910 1436 | 6705ed 1437 | 56e331 1438 | d13fed 1439 | bc52d6 1440 | acc858 1441 | 728f0f 1442 | ad4d71 1443 | e1a827 1444 | 9376b0 1445 | ea7245 1446 | 2bc13b 1447 | bc26e2 1448 | 8bc25f 1449 | e55885 1450 | 8140a0 1451 | 8.69E+13 1452 | e49f5a 1453 | aaffc3 1454 | 806043 1455 | 3460be 1456 | f3d12c 1457 | b632a4 1458 | c7e9b7 1459 | 703f3d 1460 | eabfe5 1461 | e02a84 1462 | ac530f 1463 | 12b10b 1464 | 88f59e 1465 | f816a7 1466 | 617864 1467 | 59d31e 1468 | 01d6a1 1469 | aa5cf1 1470 | 1939f9 1471 | e237d2 1472 | 367031 1473 | 5e5661 1474 | 4e7df9 1475 | d21d66 1476 | d9f606 1477 | a2feb1 1478 | 83b2a7 1479 | 21c55e 1480 | f5950f 1481 | 75841e 1482 | 795850 1483 | 3a09b9 1484 | f7cbc6 1485 | f173db 1486 | 04ad6d 1487 | 8b447e 1488 | ef58e9 1489 | 1e728c 1490 | 70cba2 1491 | b82b31 1492 | 9bd9c6 1493 | 9fccc7 1494 | ea336e 1495 | d3d577 1496 | 887760 1497 | e73eac 1498 | bba4dc 1499 | 3e61b8 1500 | 9e2ccf 1501 | 0ee07b 1502 | a93bef 1503 | 5b7e79 1504 | 6c0ce5 1505 | 463209 1506 | e268f3 1507 | c53816 1508 | b73414 1509 | 11f482 1510 | f8c44e 1511 | 0f397d 1512 | 83bfe8 1513 | 4f1112 1514 | a9836b 1515 | b69fc8 1516 | 8.54E+03 1517 | f12748 1518 | 3a9038 1519 | 2b65fd 1520 | d1db0f 1521 | 2e564e 1522 | ba69f5 1523 | 3c7a23 1524 | 13b72d 1525 | 1.66E+08 1526 | a0814e 1527 | 78a722 1528 | 0b4b31 1529 | 012f72 1530 | f1809b 1531 | 89cec0 1532 | 649b87 1533 | e9b5af 1534 | 47c0c0 1535 | 32b11a 1536 | b0441d 1537 | fb35c4 1538 | e31c6d 1539 | 5eec9d 1540 | fc7cbf 1541 | 8ccdcb 1542 | b91391 1543 | 2bb137 1544 | ed3ab9 1545 | 11225e 1546 | f239a7 1547 | 748c43 1548 | 8cd73e 1549 | b1d52e 1550 | 9f41e9 1551 | 4c1869 1552 | 26acbc 1553 | -------------------------------------------------------------------------------- /data-raw/available_random_ids.md: -------------------------------------------------------------------------------- 1 | The file data-raw/available_random_ids.csv contains random ids that you can use to identify new equations. Every time you use an id from this list, you should remove it from this list. 2 | 3 | This chunk shows how the random ids were created. 4 | 5 | ``` 6 | # WARNING 7 | # This chunk should not be re-run. If you re-run it, you will change the random 8 | # ids. 9 | available_ids <- tibble::tibble(random_id = ids::random_id(2000, bytes = 3)) 10 | write_csv(available_ids, here("data-raw/available_random_ids.csv")) 11 | ``` 12 | -------------------------------------------------------------------------------- /data-raw/climatezones.R: -------------------------------------------------------------------------------- 1 | # To cite package ‘kgc’ in publications use: 2 | # 3 | # Chelsey Bryant, Nicholas R. Wheeler, Franz 4 | # Rubel and Roger H. French (2017). kgc: 5 | # Koeppen-Geiger Climatic Zones. R package 6 | # version 1.0.0.2. 7 | # https://CRAN.R-project.org/package=kgc 8 | # 9 | # A BibTeX entry for LaTeX users is 10 | # 11 | # @Manual{, 12 | # title = {kgc: Koeppen-Geiger Climatic Zones}, 13 | # author = {Chelsey Bryant and Nicholas R. Wheeler and Franz Rubel and Roger H. French}, 14 | # year = {2017}, 15 | # note = {R package version 1.0.0.2}, 16 | # url = {https://CRAN.R-project.org/package=kgc}, 17 | # } 18 | climatezones <- kgc::climatezones 19 | use_data(climatezones, internal = TRUE, overwrite = TRUE) 20 | -------------------------------------------------------------------------------- /data-raw/csv_database/equations.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data-raw/csv_database/equations.csv -------------------------------------------------------------------------------- /data-raw/csv_database/equations_metadata.csv: -------------------------------------------------------------------------------- 1 | Column,Field,Description,Column_type,Field_codes,Units,Range 2 | 1 / A,ref_id,Unique reference identification number for biomass equation source. Links to Reference table.,character,NA,NA,NA 3 | 2 / B,equation_id,Unique equation identification number given arbitrarily. Links to Site_Species table.,character,NA,NA,NA 4 | 3 / C,equation_allometry,Equation to calculate biomass (includes coefficients given in original publication),character,NA,NA,NA 5 | 4 / D,equation_form,"Algebraic form of the biomass equation (as function of DBH, HT, WD or others)",character,NA,NA,NA 6 | 5 / E,dependent_variable,Tree component characterized by the equation,character,NA,NA,NA 7 | 6 / F,independent_variable,Parameters included in biomass model (HT: tree height (m); DBH: diameter breast heigh (1.3 m); DBA: diameter at base; WD: wood density),character,NA,"mm, cm, inch",NA 8 | 7 / G,equation_taxa,"Species, genus, family, or plant group for which the allometry was developed (sometimes used as proxy species to calculate AGB when a specific-species equation is not available)",character (string),NA,NA,NA 9 | 8 / H,allometry_specificity,"Specific taxonomic level for which the biomass equation was developed (species, genus, family or plant group)",character,NA,NA,NA 10 | 9 / I,equation_categ,"Allometric equation category base on extend of original prediction model: ""fa_spec"" family specific model; ""genus_spe"" genus specific; ""site_spec"" and ""sp_site_spec"" equations built on ForestGEO sites; ""sp_spec"" prediction models focus on a specific species; ""generic"" equation applicable to a broader regional scale",character,fa_spec; generic; genus_spec; site_spec; sp_site_spe; sp_spec,NA,NA 11 | 10 / J,geographic_area,Broad geographic location from which trees were sampled to develop the original equation,character,NA,NA,NA 12 | 11 / K,original_coord,Latitude and longitude as given in original publication,character,NA,NA,NA 13 | 12 / L,lat,"Latitude expressed in decimal degrees. Positive latitudes are north of the equator, negative latitudes are south of the equator. Used NOAA for conversion: https://www.ngs.noaa.gov/NCAT/",numeric,NA,NA,(18) / (66) 14 | 13 / M,long,"Longitude expressed in decimal degrees. Positive longitudes are east of Prime Meridian, negative longitudes are west of the Prime Meridian. Used NOAA for conversion: https://www.ngs.noaa.gov/NCAT/",numeric,NA,NA,(-155) / (131) 15 | 14 / N,elev_m,Elevation in meters above sea level (sometimes a range is given). Data from original publication or estimated by using an online tool to get elevation from coordinates (https://www.maps.ie/coordinates.html),numeric,NA,meters,(3) / (3500) 16 | 15 / O,geography_notes,"Notes pertaining to lat, long, location, or topography",character,NA,NA,NA 17 | 16 / P,mat_C,Mean annual temperature in Celsius degrees as original publication or predicted using the latitude and longitude in the WorldClim database.,numeric,NA,celsius degrees,(-4.9) / (25) 18 | 17 / Q,min.temp_C,Mean temperature of the coldest month,numeric,NA,celsius degrees,(-31) / (5.7) 19 | 18 / R,max.temp_C,Mean temperature of the warmest month,numeric,NA,celsius degrees,(12) / (32) 20 | 19 / S,map_mm,Mean annual precipitation in millimeters (multiply by 25.4 to convert from inch to mm) or predicted using the latitude and longitude in the WorldClim database.,numeric,NA,mm,(216) / (6000) 21 | 20 / T,frost_free_period_days,Frost free period (days) as reported or inferred from original publication,numeric,NA,NA,NA 22 | 21 / U,climate_notes,Climate details not included in equation table,character,NA,NA,NA 23 | 22 / V,stand_age_range_yr,Stand age (or range) as reported or inferred from original publication,numeric,NA,NA,NA 24 | 23 / W,stand_age_history,Qualitative description of the stand history reported or inferred from original publication,character,NA,NA,NA 25 | 24 / X,stand_basal_area_m2_ha,Stand basal as reported in original publication (m2 x ha),,NA,NA,NA 26 | 25 / Y,stand_trees_ha,Number of trees per hectare (average or absolute) as reported in original publication,,NA,NA,NA 27 | 26 / Z,forest_description,"Brief description of stand, summarized from original publication, including species composition",character,NA,NA,NA 28 | 27 / AA,ecosystem_type,"General classification on terrestrial ecosystem (tropical forest, temperate forest, boreal forest, mountain forest, desert, grassland)",character,NA,NA,NA 29 | 28 / AB,koppen,"Koppen climate classification, estimated using the package 'kgc"" (based on lat/long) or by visual estimates from a Koppen zones map, especially for generic equations.",character,Multiple,NA,NA 30 | 29 / AC,dbh_min_cm,Minimum DBH (cm) sampled to develop the equation,numeric,NA,cm,(0.1) -/ (31) 31 | 30 / AD,dbh_max_cm,Maximum DBH (cm) sampled to develop the equation,numeric,NA,cm,(0.69) / (614) 32 | 31 / AE,sample_size,Number of trees sampled to develop the equation,integer,NA,NA,(3) / (5397) 33 | 32 / AF,collection_year,Year(s) of measurement if in publication,integer,NA,NA,NA 34 | 33 / AG,dbh_units_original,DBH unit used in original publication,character,cm: centimeters; inch: inches; mm: millimeters,"cm, inch, mm",NA 35 | 34 / AH,dbh_unit_cf,Conversion factor applied to convert DBH unit used in original publication into an equivalent expressed in cm. Multiply by number given in table.,numeric,NA,NA,NA 36 | 35 / AI,output_units_original,Mass or length unit used in original publication,character,g= grams; kg= kilograms; lbs= pounds; metric_ton= metric ton; Mg= megagrams; m= meters,"g, kg, Mg, m",NA 37 | 36 /AJ,output_units_cf,Conversion factor applied to convert unit used in original publication (mass or length) into an equivalent expressed in kg or m. Multiply by number given in table.,numeric,NA,NA,NA 38 | 37 / AK,allometry_development_method,"Method used to develop the allometry. Traditionally, this is done by harvesting whole trees, drying, and weighing (""harvest""). However, we anticipate that many future allometries will be developed using ground-based LiDAR (""lidar"").",character,harvest; lidar,NA,NA 39 | 38 / AL,regression_model,Regression model used in original publication,character,NA,NA,NA 40 | 39 / AM,r_squared,Original R-squared value given in publication for fitted regression,numeric,NA,NA,NA 41 | 40 / AN,other_equations_tested,Comparable models if reported in publication (given equation form),character,NRA - Not Readily Available,NA,NA 42 | 41 / AO,log_biomass,Whether the regression fit is done with biomass as the response variable (i.e log(biomass) base 10),numeric,0 - false; 1 - true,NA,NA 43 | 42 / AP,bias_corrected,Indicates if a correction factor (CF) or a relative standard error (RSE) was included in model,numeric,0 - false; 1 - true,NA,NA 44 | 43 / AQ,bias_correction_factor,Correction factor for a bias introduced by logarithmic transformation of the data; pulled from original publication. NA indicates that bias correction is included in model (and no CF was provided).,numeric,NA,NA,NA 45 | 44 / AR,notes_fitting_model,Other details on statistical methods,character,NA,NA,NA 46 | 45 / AS,original_equation_id,Unique identification or clues given in original publications,character,NA,NA,NA 47 | 46 / AT,original_data_availability,Indicates whether or not the original source data is available,character,"NRA= Not Readily Available, Yes= data accessible",NA,NA 48 | 47 / AU,equation_notes,Notes or error message to indicate any pitfall that could spoil the AGB estimate based on equation,character,NA,NA,NA 49 | -------------------------------------------------------------------------------- /data-raw/csv_database/missing_values.csv: -------------------------------------------------------------------------------- 1 | Code,Definition,Description 2 | NA,Not Applicable,Data does not apply to that particular case 3 | NAC,Not Acquired,Information may be available but has not been acquired. 4 | NRA,Not Readily Available,"Information was not readily available to the authors (e.g., no ready access to the publication, language barrier)." 5 | NI,No Information,No information available in original publication 6 | -------------------------------------------------------------------------------- /data-raw/csv_database/references.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data-raw/csv_database/references.csv -------------------------------------------------------------------------------- /data-raw/csv_database/references_metadata.csv: -------------------------------------------------------------------------------- 1 | Column,Field,Description,Colum_type 2 | 1 / A,ref_id,Unique reference identification number to our data source. Links to multiple tables.,numeric 3 | 2 / B,ref_doi,Publication DOI (Digital object identifier),character (string) 4 | 3 / C,ref_author,Last name of first author of a cited publication,character (string) 5 | 4 / D,ref_year,Year of publication,numeric 6 | 5 / E,ref_title,Title of publication,character (string) 7 | 6 / F,ref_journal,"Journal, book, report where published",character (string) 8 | 7 / G,References full citation,Full citation (kept for easy use),character (string) 9 | -------------------------------------------------------------------------------- /data-raw/csv_database/sites_info.csv: -------------------------------------------------------------------------------- 1 | Site,site,lat,long,elevation.m,koppen 2 | Changbaishan,changbaishan,42.38,128.08,785,Dwb 3 | Gutianshan,gutianshan,29.25,118.12,448,Cfa 4 | Harvard Forest,harvard forest,42.54,-72.18,371,Dfb 5 | Heishiding,heishiding,23.27,111.53,128,Cfa 6 | Indian Cave,indian cave,40.25,-95.54,285,Dfa 7 | Lilly Dickey Woods,lilly dickey,39.24,-86.22,275,Cfa 8 | Michigan Big Woods,michigan big woods,42.46,-84,270,Dfa 9 | Niobrara,niobara,42.78,-100.02,694,Dfa 10 | Ordway-Swisher,ordway-swisher,29.692414,-81.993419,51,Cfa 11 | SCBI,scbi,38.89,-78.15,350,Cfa 12 | Scotty Creek,scotty creek,61.3,-121.3,165,Dfc 13 | SERC,serc,38.89,-76.56,29,Cfa 14 | Speulderbos,speulderbos,52.25,5.7,63,Cfb 15 | Tiantongshan,tiantongshan,29.81,121.78,344,Cfa 16 | Traunstein,traunstein,47.93,12.66,606,Dfb 17 | Tyson Research Center,tyson,38.52,-90.56,221,Cfa 18 | University of California-Santa Cruz,ucsc,37.012,-122.075,311,Csb 19 | University of Maryland-Baltimore County,umbc,39.25,-76.708,48,Cfa 20 | Utah,utah,37.66,-112.85,3013,Cfb 21 | Wabikon,wabikon,45.55,-88.79,494,Dfb 22 | Wind River,wind river,45.82,-121.96,404,Csb 23 | Wytham Woods,wytham woods,51.77,-1.34,162,Cfb 24 | Yosemite National Park,yosemite,37.77,-119.82,1796,Csb 25 | Zofin,zofin,48.66,14.71,814,Cfb 26 | -------------------------------------------------------------------------------- /data-raw/csv_database/sitespecies.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data-raw/csv_database/sitespecies.csv -------------------------------------------------------------------------------- /data-raw/csv_database/sitespecies_metadata.csv: -------------------------------------------------------------------------------- 1 | Column,Field,Description,Column_type 2 | 1 / A,site,ForestGEO site name (full site name or abbreviated),character 3 | 2 / B,family,"Plant family name revised in Taxonomic Name Resolution Services (TNRS), an online free tool for correcting and standardizing plant names.",character 4 | 3 / C,genus,Plant genus name,character 5 | 4 / D,species,"Plant specific name or epithet. When referring to a plant in a genus if the individual was not identified at the species level, we use 'sp.' If an epithet is preceded by the letter 'x' it indicates a hybrid form (i.e. Tilia x europaea)",character 6 | 5 / E,variety,Variation recognized within a species,character 7 | 6 / F,subspecies,Subspecies recognized within a species,character 8 | 7 / G,latin_name,"Plant name as used by ForestGEO sites (names corrected here using TNRS, when necessary)",character 9 | 9 / I,species_code,"Species code used at the ForestGEO site, variable per site, even if representing same species.",character 10 | 10 / J,life_form,Common growth form for a given plant species,character 11 | 11 / K,warning,"Informative notes, sometimes critical for biomass calculation",character 12 | -------------------------------------------------------------------------------- /data-raw/data.R: -------------------------------------------------------------------------------- 1 | # Source this file to update all exported data. 2 | 3 | library(usethis) 4 | library(readr) 5 | library(purrr) 6 | library(fs) 7 | 8 | # remember that your working directory should be allodb, use 'here" or getwd() 9 | here::here() 10 | getwd() 11 | 12 | path_db <- "data-raw/csv_database" 13 | db_nms <- path_ext_remove(path_file(dir_ls(path_db))) 14 | 15 | db_ls <- dir_ls(path_db) %>% 16 | map(~ read_csv(.x, col_types = cols(.default = "c"))) %>% 17 | set_names(db_nms) 18 | 19 | list2env(db_ls, globalenv()) 20 | 21 | # Ensure all equations are lowercase 22 | equations$equation_allometry <- tolower(equations$equation_allometry) 23 | 24 | # These datasets seem to only exist in data/ 25 | devtools::load_all() 26 | # They once lacked the tbl subclass 27 | scbi_stem1 <- tibble::as_tibble(scbi_stem1) 28 | koppenMatrix <- tibble::as_tibble(koppenMatrix) 29 | gymno_genus <- tibble::as_tibble(gymno_genus) 30 | genus_family <- tibble::as_tibble(genus_family) 31 | 32 | use_data( 33 | equations, 34 | equations_metadata, 35 | missing_values, 36 | references, 37 | references_metadata, 38 | sitespecies, 39 | sitespecies_metadata, 40 | sites_info, 41 | scbi_stem1, 42 | koppenMatrix, 43 | gymno_genus, 44 | genus_family, 45 | overwrite = TRUE 46 | ) 47 | -------------------------------------------------------------------------------- /data-raw/shrub_species.R: -------------------------------------------------------------------------------- 1 | shrub_species <- readr::read_rds(here::here("data-raw", "shrub_species.rds")) 2 | usethis::use_data(shrub_species, overwrite = TRUE) 3 | -------------------------------------------------------------------------------- /data-raw/shrub_species.rds: -------------------------------------------------------------------------------- 1 | X 2 |  shrub_species -------------------------------------------------------------------------------- /data/equations.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/equations.rda -------------------------------------------------------------------------------- /data/equations_metadata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/equations_metadata.rda -------------------------------------------------------------------------------- /data/genus_family.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/genus_family.rda -------------------------------------------------------------------------------- /data/gymno_genus.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/gymno_genus.rda -------------------------------------------------------------------------------- /data/koppenMatrix.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/koppenMatrix.rda -------------------------------------------------------------------------------- /data/missing_values.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/missing_values.rda -------------------------------------------------------------------------------- /data/references.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/references.rda -------------------------------------------------------------------------------- /data/references_metadata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/references_metadata.rda -------------------------------------------------------------------------------- /data/scbi_stem1.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/scbi_stem1.rda -------------------------------------------------------------------------------- /data/shrub_species.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/shrub_species.rda -------------------------------------------------------------------------------- /data/sites_info.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/sites_info.rda -------------------------------------------------------------------------------- /data/sitespecies.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/sitespecies.rda -------------------------------------------------------------------------------- /data/sitespecies_metadata.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/data/sitespecies_metadata.rda -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | AGB 2 | Akre 3 | Allometric 4 | Bohn 5 | CMD 6 | Codecov 7 | DBH 8 | DBHs 9 | ForestGEO 10 | Koppen 11 | Koppen's 12 | ORCID 13 | Quercus 14 | SCBI 15 | Teixeira 16 | aboveground 17 | agb 18 | al 19 | allometric 20 | allometries 21 | allometry 22 | belowground 23 | boreal 24 | cdot 25 | dbh 26 | eg 27 | et 28 | extratropical 29 | extratropics 30 | ggplot 31 | ies 32 | mathcal 33 | recalibrated 34 | recalibration 35 | rubra 36 | -------------------------------------------------------------------------------- /man/allodb-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/allodb-package.R 3 | \docType{package} 4 | \name{allodb-package} 5 | \alias{allodb} 6 | \alias{allodb-package} 7 | \title{allodb: Tree Biomass Estimation at Extra-Tropical Forest Plots} 8 | \description{ 9 | Standardize and simplify the tree biomass estimation process across globally distributed extratropical forests. 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://docs.ropensci.org/allodb/} 15 | \item \url{https://github.com/ropensci/allodb} 16 | \item Report bugs at \url{https://github.com/ropensci/allodb/issues} 17 | } 18 | 19 | } 20 | \author{ 21 | \strong{Maintainer}: Erika Gonzalez-Akre \email{ekagonzalez@gmail.com} (\href{https://orcid.org/0000-0001-8305-6672}{ORCID}) [copyright holder] 22 | 23 | Authors: 24 | \itemize{ 25 | \item Camille Piponiot \email{camille.piponiot@gmail.com} (\href{https://orcid.org/0000-0002-3473-1982}{ORCID}) 26 | \item Mauro Lepore \email{maurolepore@gmail.com} (\href{https://orcid.org/0000-0002-1986-7988}{ORCID}) 27 | \item Kristina Anderson-Teixeira \email{TeixeiraK@si.edu} (\href{https://orcid.org/0000-0001-8461-9713}{ORCID}) 28 | } 29 | 30 | Other contributors: 31 | \itemize{ 32 | \item Jeffrey Hanson \email{jeffrey.hanson@uqconnect.edu.au} [reviewer] 33 | \item Jonas Stillhard \email{jonas.stillhard@wsl.ch} [reviewer] 34 | } 35 | 36 | } 37 | \keyword{internal} 38 | -------------------------------------------------------------------------------- /man/equations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{equations} 5 | \alias{equations} 6 | \alias{equations_metadata} 7 | \title{Tables of allometric equations and associated metadata} 8 | \format{ 9 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 570 rows and 47 columns. 10 | 11 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 47 rows and 7 columns. 12 | } 13 | \source{ 14 | See \link{references} for equations original sources. 15 | } 16 | \usage{ 17 | equations 18 | 19 | equations_metadata 20 | } 21 | \description{ 22 | \itemize{ 23 | \item \link{equations}: Table of allometric equations. 24 | \item \link{equations_metadata}: Explanation of columns for \link{equations} table. 25 | } 26 | } 27 | \details{ 28 | A compilation of best available allometry equations to calculate tree 29 | above-ground biomass (AGB) per species based on extratropical ForestGEO 30 | sites. 31 | } 32 | \examples{ 33 | # preview the datasets 34 | print(head(equations)) 35 | print(head(equations_metadata)) 36 | } 37 | \seealso{ 38 | Other database datasets: 39 | \code{\link{missing_values}}, 40 | \code{\link{references}}, 41 | \code{\link{sites_info}}, 42 | \code{\link{sitespecies}} 43 | } 44 | \concept{database datasets} 45 | \keyword{datasets} 46 | -------------------------------------------------------------------------------- /man/est_params.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/est_params.R 3 | \name{est_params} 4 | \alias{est_params} 5 | \title{Calibrate new allometric equations} 6 | \usage{ 7 | est_params( 8 | genus, 9 | coords, 10 | species = NULL, 11 | new_eqtable = NULL, 12 | wna = 0.1, 13 | w95 = 500, 14 | nres = 10000 15 | ) 16 | } 17 | \arguments{ 18 | \item{genus}{a character vector, containing the genus (e.g. "Quercus") of 19 | each tree.} 20 | 21 | \item{coords}{a numeric vector of length 2 with longitude and latitude (if 22 | all trees were measured in the same location) or a matrix with 2 numerical 23 | columns giving the coordinates of each tree.} 24 | 25 | \item{species}{a character vector (same length as genus), containing the 26 | species (e.g. "rubra") of each tree. Default is \code{NULL}, when no species 27 | identification is available.} 28 | 29 | \item{new_eqtable}{Optional. An equation table created with the 30 | \code{\link[=new_equations]{new_equations()}} function. Default is the compiled \emph{allodb} equation 31 | table.} 32 | 33 | \item{wna}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 34 | function to determine the dbh-related and sample-size related weights 35 | attributed to equations without a specified dbh range or sample size, 36 | respectively. Default is 0.1.} 37 | 38 | \item{w95}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 39 | function to determine the value at which the sample-size-related weight 40 | reaches 95\% of its maximum value (max=1). Default is 500.} 41 | 42 | \item{nres}{number of resampled values. Default is "1e4".} 43 | } 44 | \value{ 45 | An object of class "data.frame" of fitted coefficients (columns) of 46 | the non-linear least-square regression: 47 | \deqn{AGB = a * dbh ^ b + e, \space 48 | \mathit{with} \space e ~ N(0, sigma^2)}{AGB = a * dbh ^ b + e, with e ~ 49 | N(0, sigma^2)} 50 | } 51 | \description{ 52 | This function calibrates new allometric equations from sampling previous 53 | ones. New allometric equations are calibrated for each species and location 54 | by resampling the original compiled equations; equations with a larger sample 55 | size, and/or higher taxonomic rank, and climatic similarity with the species 56 | and location in question are given a higher weight in this process. 57 | } 58 | \examples{ 59 | # calibrate new allometries for all Lauraceae species 60 | lauraceae <- subset(scbi_stem1, Family == "Lauraceae") 61 | est_params( 62 | genus = lauraceae$genus, 63 | species = lauraceae$species, 64 | coords = c(-78.2, 38.9) 65 | ) 66 | } 67 | \seealso{ 68 | \code{\link[=weight_allom]{weight_allom()}}, \code{\link[=new_equations]{new_equations()}}. 69 | } 70 | -------------------------------------------------------------------------------- /man/figures/README-est-params-acer-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/man/figures/README-est-params-acer-1.png -------------------------------------------------------------------------------- /man/figures/README-resample-acer-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/allodb/1cfe846eb4fd32e7561dcc2dd7a932354b2b3b33/man/figures/README-resample-acer-1.png -------------------------------------------------------------------------------- /man/genus_family.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{genus_family} 5 | \alias{genus_family} 6 | \title{Genus and family table for selected ForestGEO sites} 7 | \format{ 8 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 248 rows and 2 columns. 9 | } 10 | \usage{ 11 | genus_family 12 | } 13 | \description{ 14 | Genus and their associated family identified in the extratropical ForestGEO 15 | sites used in allodb. 16 | } 17 | \examples{ 18 | # preview the dataset 19 | print(head(genus_family)) 20 | } 21 | \seealso{ 22 | Other datasets: 23 | \code{\link{gymno_genus}}, 24 | \code{\link{koppenMatrix}}, 25 | \code{\link{scbi_stem1}}, 26 | \code{\link{shrub_species}} 27 | } 28 | \concept{datasets} 29 | \keyword{datasets} 30 | -------------------------------------------------------------------------------- /man/get_biomass.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_biomass.R 3 | \name{get_biomass} 4 | \alias{get_biomass} 5 | \title{Compute tree aboveground biomass (AGB) based on allometric equations} 6 | \usage{ 7 | get_biomass( 8 | dbh, 9 | genus, 10 | coords, 11 | species = NULL, 12 | new_eqtable = NULL, 13 | wna = 0.1, 14 | w95 = 500, 15 | nres = 10000 16 | ) 17 | } 18 | \arguments{ 19 | \item{dbh}{a numeric vector containing tree diameter at breast height (dbh) 20 | measurements, in cm.} 21 | 22 | \item{genus}{a character vector (same length as dbh), containing the genus 23 | (e.g. "Quercus") of each tree.} 24 | 25 | \item{coords}{a numeric vector of length 2 with longitude and latitude (if 26 | all trees were measured in the same location) or a matrix with 2 numerical 27 | columns giving the coordinates of each tree.} 28 | 29 | \item{species}{a character vector (same length as dbh), containing the 30 | species (e.g. "rubra") of each tree. Default is \code{NULL}, when no species 31 | identification is available.} 32 | 33 | \item{new_eqtable}{Optional. An equation table created with the 34 | \code{\link[=new_equations]{new_equations()}} function.} 35 | 36 | \item{wna}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 37 | function to determine the dbh-related weight attributed to equations 38 | without a specified dbh range. Default is 0.1.} 39 | 40 | \item{w95}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 41 | function to determine the value at which the sample-size-related weight 42 | reaches 95\% of its maximum value (max=1). Default is 500.} 43 | 44 | \item{nres}{number of resampled values. Default is "1e4".} 45 | } 46 | \value{ 47 | A "numeric" vector of the same length as dbh, containing AGB value 48 | (in kg) for every stem. 49 | } 50 | \description{ 51 | This function calculates the aboveground biomass (or other tree components) 52 | of a given tree based on published allometric equations. Users need to 53 | provide a table (i.e. dataframe) with DBH (cm), parsed species Latin names, 54 | and site(s) coordinates. The biomass of all trees in one (or several) 55 | censuses can be estimated using this function. 56 | } 57 | \details{ 58 | \code{allodb} estimates AGB by calibrating a new allometric equation for each 59 | taxon (arguments \code{genus} and \code{species}) and location (argument \code{coords}) in 60 | the user-provided census data. The new allometric equation is based on a set 61 | of allometric equations that can be customized using the \code{new_eqtable} 62 | argument. Each equation is then given a weight with the \code{\link[=weight_allom]{weight_allom()}} 63 | function, based on: 1) its original sample size (numbers of trees used to 64 | develop a given allometry), 2) its climatic similarity with the target 65 | location, and 3) its taxonomic similarity with the target taxon (see 66 | documentation of the \code{\link[=weight_allom]{weight_allom()}} function). The final weight attributed 67 | to each equation is the product of those three weights. Equations are then 68 | resampled with the\code{\link[=resample_agb]{resample_agb()}} function: the number of samples per 69 | equation is proportional to its weight, and the total number of samples is 70 | provided by the argument \code{nres}. The resampling is done by drawing DBH values 71 | from a uniform distribution on the DBH range of the equation, and estimating 72 | the AGB with the equation. The couples of values (DBH, AGB) obtained are then 73 | used in the function \code{\link[=est_params]{est_params()}} to calibrate a new allometric equation, 74 | by applying a linear regression to the log-transformed data. The parameters 75 | of the new allometric equations are then used in the \code{\link[=get_biomass]{get_biomass()}} function 76 | by back-transforming the AGB predictions based on the user-provided DBHs. 77 | } 78 | \section{Warning}{ 79 | 80 | The function can run into some memory problems when used on large datasets 81 | (usually several hundred thousand observations). 82 | } 83 | 84 | \examples{ 85 | # Estimate biomass of all individuals from the Lauraceae family at the SCBI 86 | # plot 87 | lau <- subset(scbi_stem1, Family == "Lauraceae") 88 | lau$agb <- get_biomass(lau$dbh, lau$genus, lau$species, 89 | coords = c(-78.2, 38.9) 90 | ) 91 | lau 92 | 93 | # Estimate biomass from multiple sites (using scbi_stem1 as example with 94 | # multiple coord) 95 | dat <- scbi_stem1[1:100, ] 96 | dat$long <- c(rep(-78, 50), rep(-80, 50)) 97 | dat$lat <- c(rep(40, 50), rep(41, 50)) 98 | dat$biomass <- get_biomass( 99 | dbh = dat$dbh, 100 | genus = dat$genus, 101 | species = dat$species, 102 | coords = dat[, c("long", "lat")] 103 | ) 104 | dat 105 | } 106 | \seealso{ 107 | \code{\link[=weight_allom]{weight_allom()}}, \code{\link[=new_equations]{new_equations()}} 108 | } 109 | -------------------------------------------------------------------------------- /man/gymno_genus.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{gymno_genus} 5 | \alias{gymno_genus} 6 | \title{Gymnosperms identified in selected ForestGEO sites} 7 | \format{ 8 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 95 rows and 3 columns. 9 | } 10 | \usage{ 11 | gymno_genus 12 | } 13 | \description{ 14 | Table with genus and their associated family for Gymnosperms identified in 15 | the ForestGEO sites used in allodb. 16 | } 17 | \examples{ 18 | # preview the dataset 19 | print(head(gymno_genus)) 20 | } 21 | \seealso{ 22 | Other datasets: 23 | \code{\link{genus_family}}, 24 | \code{\link{koppenMatrix}}, 25 | \code{\link{scbi_stem1}}, 26 | \code{\link{shrub_species}} 27 | } 28 | \concept{datasets} 29 | \keyword{datasets} 30 | -------------------------------------------------------------------------------- /man/illustrate_allodb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/illustrate_allodb.R 3 | \name{illustrate_allodb} 4 | \alias{illustrate_allodb} 5 | \title{Illustrate the resampling of AGB values used in \emph{allodb}} 6 | \usage{ 7 | illustrate_allodb( 8 | genus, 9 | coords, 10 | species = NULL, 11 | new_eqtable = NULL, 12 | logxy = FALSE, 13 | neq = 10, 14 | eqinfo = "equation_taxa", 15 | wna = 0.1, 16 | w95 = 500, 17 | nres = 10000 18 | ) 19 | } 20 | \arguments{ 21 | \item{genus}{A character value, containing the genus (e.g. "Quercus") of the 22 | tree.} 23 | 24 | \item{coords}{A numeric vector of length 2 with longitude and latitude.} 25 | 26 | \item{species}{A character value, containing the species (e.g. "rubra") of 27 | the tree. Default is \code{NULL}, when no species identification is available.} 28 | 29 | \item{new_eqtable}{Optional. An equation table created with the 30 | \code{\link[=new_equations]{new_equations()}} function. Default is the base \emph{allodb} equation 31 | table.} 32 | 33 | \item{logxy}{Logical: should values be plotted on a log scale? Default is 34 | \code{FALSE}.} 35 | 36 | \item{neq}{Number of top equations in the legend. Default is 10, meaning that 37 | the 10 equations with the highest weights are shown in the legend.} 38 | 39 | \item{eqinfo}{Which column(s) of the equation table should be used in the 40 | legend? Default is "equation_taxa".} 41 | 42 | \item{wna}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 43 | function to determine the dbh-related and sample-size related weights 44 | attributed to equations without a specified dbh range or sample size, 45 | respectively. Default is 0.1.} 46 | 47 | \item{w95}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 48 | function to determine the value at which the sample-size-related weight 49 | reaches 95\% of its maximum value (max=1). Default is 500.} 50 | 51 | \item{nres}{number of resampled values. Default is "1e4".} 52 | } 53 | \value{ 54 | An object of class "ggplot" showing all resampled dbh-agb values. The 55 | top equations used are shown in the legend. The red curve on the graph 56 | represents the final fitted equation. 57 | } 58 | \description{ 59 | This function illustrates the resampling of AGB values used in \emph{allodb}. It 60 | creates objects of class "ggplot". 61 | } 62 | \examples{ 63 | illustrate_allodb( 64 | genus = "Quercus", 65 | species = "rubra", 66 | coords = c(-78.2, 38.9) 67 | ) 68 | } 69 | \seealso{ 70 | \code{\link[=weight_allom]{weight_allom()}}, \code{\link[=new_equations]{new_equations()}}. 71 | } 72 | -------------------------------------------------------------------------------- /man/koppenMatrix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{koppenMatrix} 5 | \alias{koppenMatrix} 6 | \title{Koppen climate classification matrix} 7 | \format{ 8 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 900 rows and 3 columns. 9 | } 10 | \usage{ 11 | koppenMatrix 12 | } 13 | \description{ 14 | A table built to facilitate the comparison between the Koppen climate of a 15 | site and the allometric equation in question. 16 | } 17 | \details{ 18 | The value of column \code{we} is the weight given to the combination of Koppen 19 | climates in columns \code{zone1} and \code{zone2}; the table is symmetric: \code{zone1} and 20 | \code{zone2} can be interchanged. This weight is calculated in 3 steps: (1) if the 21 | main climate group (first letter) is the same, the climate weight starts at 22 | 0.4; if one of the groups is "C" (temperate climate) and the other is "D" 23 | (continental climate), the climate weight starts at 0.2 because the 2 groups 24 | are considered similar enough; otherwise, the weight is 0; (2) if the 25 | equation and site belong to the same group, the weight is incremented by an 26 | additional value between 0 and 0.3 based on precipitation pattern similarity 27 | (second letter of the Koppen zone), and (3) by an additional value between 0 28 | and 0.3 based on temperature pattern similarity (third letter of the Koppen 29 | zone). The resulting weight has a value between 0 (different climate groups) 30 | and 1 (exactly the same climate classification). 31 | } 32 | \examples{ 33 | # preview the dataset 34 | print(head(koppenMatrix)) 35 | } 36 | \seealso{ 37 | Other datasets: 38 | \code{\link{genus_family}}, 39 | \code{\link{gymno_genus}}, 40 | \code{\link{scbi_stem1}}, 41 | \code{\link{shrub_species}} 42 | } 43 | \concept{datasets} 44 | \keyword{datasets} 45 | -------------------------------------------------------------------------------- /man/missing_values.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{missing_values} 5 | \alias{missing_values} 6 | \title{Explanations of missing values codes} 7 | \format{ 8 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 4 rows and 3 columns. 9 | } 10 | \usage{ 11 | missing_values 12 | } 13 | \description{ 14 | Explanation of the codes used to indicate missing information in equation 15 | table. 16 | } 17 | \examples{ 18 | # preview the dataset 19 | print(head(missing_values)) 20 | } 21 | \seealso{ 22 | Other database datasets: 23 | \code{\link{equations}}, 24 | \code{\link{references}}, 25 | \code{\link{sites_info}}, 26 | \code{\link{sitespecies}} 27 | } 28 | \concept{database datasets} 29 | \keyword{datasets} 30 | -------------------------------------------------------------------------------- /man/new_equations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/new_equations.R 3 | \name{new_equations} 4 | \alias{new_equations} 5 | \title{Modify the original equation table} 6 | \usage{ 7 | new_equations( 8 | subset_taxa = "all", 9 | subset_climate = "all", 10 | subset_region = "all", 11 | subset_ids = "all", 12 | subset_output = c("Total aboveground biomass", "Whole tree (above stump)"), 13 | new_taxa = NULL, 14 | new_allometry = NULL, 15 | new_coords = NULL, 16 | new_min_dbh = NULL, 17 | new_max_dbh = NULL, 18 | new_sample_size = NULL, 19 | new_unit_dbh = "cm", 20 | new_unit_output = "kg", 21 | new_input_var = "DBH", 22 | new_output_var = "Total aboveground biomass", 23 | use_height_allom = TRUE 24 | ) 25 | } 26 | \arguments{ 27 | \item{subset_taxa}{character vector with taxa to be kept. Default is "all", 28 | in which case all taxa are kept.} 29 | 30 | \item{subset_climate}{character vector with Koppen climate classification to 31 | be kept. Default is "all", in which case all climates are kept.} 32 | 33 | \item{subset_region}{character vector with name of location(s) or 34 | country(ies) or broader region(s) (eg. "Europe", "North America") to be 35 | kept. Default is "all", in which case all regions/countries are kept.} 36 | 37 | \item{subset_ids}{character vector with equation IDs to be kept. Default is 38 | "all", in which case all equations are kept.} 39 | 40 | \item{subset_output}{What dependent variable(s) should be provided in the 41 | output? Default is "Total aboveground biomass" and "Whole tree (above 42 | stump)", other possible values are: "Bark biomass", "Branches (dead)", 43 | "Branches (live)", "Branches total (live, dead)", "Foliage total", 44 | "Height", "Leaves", "Stem (wood only)", "Stem biomass", "Stem biomass (with 45 | bark)", "Stem biomass (without bark)", "Whole tree (above and 46 | belowground)". Be aware that currently only a few equations represent those 47 | other variables, so estimated values might not be very accurate.} 48 | 49 | \item{new_taxa}{character string or vector specifying the taxon (or taxa) for 50 | which the allometry has been calibrated.} 51 | 52 | \item{new_allometry}{a character string with the allometric equation.} 53 | 54 | \item{new_coords}{a vector or matrix of coordinates (longitude, latitude) of 55 | the calibration data.} 56 | 57 | \item{new_min_dbh}{numerical value, minimum DBH for which the equation is 58 | valid (in cm). Default is \code{NULL} (nothing is added).} 59 | 60 | \item{new_max_dbh}{numerical value, maximum DBH for which the equation is 61 | valid (in cm). Default is \code{NULL} (nothing is added).} 62 | 63 | \item{new_sample_size}{number of measurements with which the allometry was 64 | calibrated. Default is \code{NULL} (nothing is added).} 65 | 66 | \item{new_unit_dbh}{character string with unit of DBH in the equation (either 67 | \code{cm}, \code{mm} or \code{inch}). Default is "cm".} 68 | 69 | \item{new_unit_output}{character string with unit of equation output (either 70 | "g", "kg", "Mg" or "lbs" if the output is a mass, or "m" if the output is a 71 | height).} 72 | 73 | \item{new_input_var}{independent variable(s) needed in the allometry. Default 74 | is "DBH", other option is "DBH, H".} 75 | 76 | \item{new_output_var}{dependent variable estimated by the allometry. Default 77 | is "Total aboveground biomass".} 78 | 79 | \item{use_height_allom}{a logical value. In \emph{allodb} we use Bohn et al. 80 | (2014) for European sites. User need to provide height allometry when 81 | needed to calculate AGB. Default is \code{TRUE}.} 82 | } 83 | \value{ 84 | An object of class "data.frame" of new equations. 85 | } 86 | \description{ 87 | This function modifies the original equation table to be used in other 88 | functions of the package including: subset the original equation table, add 89 | new equations, and choose whether to include equations with a height 90 | allometry. 91 | } 92 | \examples{ 93 | new_equations( 94 | new_taxa = "Faga", 95 | new_allometry = "exp(-2+log(dbh)*2.5)", 96 | new_coords = c(-0.07, 46.11), 97 | new_min_dbh = 5, 98 | new_max_dbh = 50, 99 | new_sample_size = 50 100 | ) 101 | } 102 | -------------------------------------------------------------------------------- /man/references.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{references} 5 | \alias{references} 6 | \alias{references_metadata} 7 | \title{Equation references and associated metadata} 8 | \format{ 9 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 57 rows and 6 columns. 10 | 11 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 7 rows and 4 columns. 12 | } 13 | \usage{ 14 | references 15 | 16 | references_metadata 17 | } 18 | \description{ 19 | \itemize{ 20 | \item \link{references}: A data frame listing all references used in \code{equation} table. 21 | \item \link{references_metadata}: Metadata for \code{reference} table. 22 | } 23 | } 24 | \details{ 25 | Bibliographical information for sourced equations. Links to the \link{equations} 26 | table by \code{ref_id}. 27 | } 28 | \examples{ 29 | # preview the datasets 30 | print(head(references)) 31 | print(head(references_metadata)) 32 | } 33 | \seealso{ 34 | Other database datasets: 35 | \code{\link{equations}}, 36 | \code{\link{missing_values}}, 37 | \code{\link{sites_info}}, 38 | \code{\link{sitespecies}} 39 | } 40 | \concept{database datasets} 41 | \keyword{datasets} 42 | -------------------------------------------------------------------------------- /man/resample_agb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/resample_agb.R 3 | \name{resample_agb} 4 | \alias{resample_agb} 5 | \title{Resample \emph{allodb} equations to calibrate new allometries} 6 | \usage{ 7 | resample_agb( 8 | genus, 9 | coords, 10 | species = NULL, 11 | new_eqtable = NULL, 12 | wna = 0.1, 13 | w95 = 500, 14 | nres = 10000 15 | ) 16 | } 17 | \arguments{ 18 | \item{genus}{a character value, containing the genus (e.g. "Quercus") of the 19 | tree.} 20 | 21 | \item{coords}{a numeric vector of length 2 with longitude and latitude.} 22 | 23 | \item{species}{a character value, containing the species (e.g. "rubra") of 24 | the tree. Default is "NULL", when no species identification is available.} 25 | 26 | \item{new_eqtable}{Optional. An equation table created with the 27 | \code{\link[=new_equations]{new_equations()}} function. Default is the original \emph{allodb} equation 28 | table.} 29 | 30 | \item{wna}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 31 | function to determine the dbh-related and sample-size related weights 32 | attributed to equations without a specified dbh range or sample size, 33 | respectively. Default is 0.1.} 34 | 35 | \item{w95}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 36 | function to determine the value at which the sample-size-related weight 37 | reaches 95\% of its maximum value (max=1). Default is 500.} 38 | 39 | \item{nres}{number of resampled values. Default is "1e4".} 40 | } 41 | \value{ 42 | An object of class "data.frame" of resampled DBHs and associated AGB 43 | from the equation table; the number of resampled DBHs is proportional to 44 | the weight provided by the \code{\link[=weight_allom]{weight_allom()}} function. 45 | } 46 | \description{ 47 | After attributing a weight to each equation in \emph{allodb} using the 48 | \code{\link[=weight_allom]{weight_allom()}} function, equations are then resampled within their original 49 | DBH range using \code{\link[=resample_agb]{resample_agb()}}: the number of resampled values for each 50 | equation is proportional to its weight. It creates S3 objects of class 51 | "numeric". 52 | } 53 | \examples{ 54 | resample_agb( 55 | genus = "Quercus", 56 | species = "rubra", 57 | coords = c(-78.2, 38.9) 58 | ) 59 | } 60 | \seealso{ 61 | \code{\link[=weight_allom]{weight_allom()}}, \code{\link[=new_equations]{new_equations()}}. 62 | } 63 | -------------------------------------------------------------------------------- /man/scbi_stem1.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{scbi_stem1} 5 | \alias{scbi_stem1} 6 | \title{Tree census data from SCBI ForestGEO plot} 7 | \format{ 8 | An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 2287 rows and 6 columns. 9 | } 10 | \source{ 11 | Full datasets for tree census data at SCBI can be requested through 12 | the ForestGEO portal (\url{https://forestgeo.si.edu/}). Census 1, 2, and 3 can 13 | also be accessed at the public GitHub repository for SCBI-ForestGEO Data 14 | (\url{https://github.com/SCBI-ForestGEO}). 15 | } 16 | \usage{ 17 | scbi_stem1 18 | } 19 | \description{ 20 | A table with tree data from the Smithsonian Conservation Biology Institute, 21 | USA (SCBI) ForestGEO dynamics plot. This dataset is an extract from the first 22 | tree census in 2008, only covering 1 hectare (SCBI plot is 25.6 ha). DBH in 23 | cm. 24 | } 25 | \examples{ 26 | # preview the datasets 27 | print(head(scbi_stem1)) 28 | } 29 | \seealso{ 30 | Other datasets: 31 | \code{\link{genus_family}}, 32 | \code{\link{gymno_genus}}, 33 | \code{\link{koppenMatrix}}, 34 | \code{\link{shrub_species}} 35 | } 36 | \concept{datasets} 37 | \keyword{datasets} 38 | -------------------------------------------------------------------------------- /man/shrub_species.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{shrub_species} 5 | \alias{shrub_species} 6 | \title{Shrub species identified in selected ForestGEO sites} 7 | \format{ 8 | An object of class \code{character} of length 1. 9 | } 10 | \usage{ 11 | shrub_species 12 | } 13 | \description{ 14 | Genus and species of shrubby plants identified in the 24 extratropical 15 | ForestGEO sites used in allodb. 16 | } 17 | \examples{ 18 | # preview the dataset 19 | print(head(shrub_species)) 20 | } 21 | \seealso{ 22 | Other datasets: 23 | \code{\link{genus_family}}, 24 | \code{\link{gymno_genus}}, 25 | \code{\link{koppenMatrix}}, 26 | \code{\link{scbi_stem1}} 27 | } 28 | \concept{datasets} 29 | \keyword{datasets} 30 | -------------------------------------------------------------------------------- /man/sites_info.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{sites_info} 5 | \alias{sites_info} 6 | \title{ForestGEO sites used in allodb} 7 | \format{ 8 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 24 rows and 6 columns. 9 | } 10 | \usage{ 11 | sites_info 12 | } 13 | \description{ 14 | Table with geographical information for extratropical ForestGEO sites used in 15 | allodb (n=24). 16 | } 17 | \details{ 18 | More details on geographical aspects of these ForestGEO sites can be found in 19 | the accompanying manuscript. 20 | } 21 | \examples{ 22 | # preview the datasets 23 | print(head(sites_info)) 24 | } 25 | \seealso{ 26 | Other database datasets: 27 | \code{\link{equations}}, 28 | \code{\link{missing_values}}, 29 | \code{\link{references}}, 30 | \code{\link{sitespecies}} 31 | } 32 | \concept{database datasets} 33 | \keyword{datasets} 34 | -------------------------------------------------------------------------------- /man/sitespecies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{sitespecies} 5 | \alias{sitespecies} 6 | \alias{sitespecies_metadata} 7 | \title{Sites and tree species used in allodb and associated metadata} 8 | \format{ 9 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 1113 rows and 10 columns. 10 | 11 | An object of class \code{spec_tbl_df} (inherits from \code{tbl_df}, \code{tbl}, \code{data.frame}) with 10 rows and 4 columns. 12 | } 13 | \usage{ 14 | sitespecies 15 | 16 | sitespecies_metadata 17 | } 18 | \description{ 19 | \itemize{ 20 | \item \link{sitespecies}: Table of extratropical ForestGEO sites in allodb (n=24) and 21 | their tree species. 22 | \item \link{sitespecies_metadata}: Metadata for \link{sitespecies} table. 23 | } 24 | } 25 | \examples{ 26 | # preview the datasets 27 | print(head(sitespecies)) 28 | print(head(sitespecies_metadata)) 29 | } 30 | \seealso{ 31 | Other database datasets: 32 | \code{\link{equations}}, 33 | \code{\link{missing_values}}, 34 | \code{\link{references}}, 35 | \code{\link{sites_info}} 36 | } 37 | \concept{database datasets} 38 | \keyword{datasets} 39 | -------------------------------------------------------------------------------- /man/weight_allom.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/weight_allom.R 3 | \name{weight_allom} 4 | \alias{weight_allom} 5 | \title{Attribute weights to equations} 6 | \usage{ 7 | weight_allom( 8 | genus, 9 | coords, 10 | species = NULL, 11 | new_eqtable = NULL, 12 | wna = 0.1, 13 | w95 = 500 14 | ) 15 | } 16 | \arguments{ 17 | \item{genus}{a character value, containing the genus (e.g. "Quercus") of the 18 | tree.} 19 | 20 | \item{coords}{a numeric vector of length 2 with longitude and latitude.} 21 | 22 | \item{species}{a character vector (same length as genus), containing the 23 | species (e.g. "rubra") of the tree. Default is \code{NULL}, when no species 24 | identification is available.} 25 | 26 | \item{new_eqtable}{Optional. An equation table created with the 27 | \code{\link[=new_equations]{new_equations()}} function.} 28 | 29 | \item{wna}{a numeric vector, this parameter is used in the \code{\link[=weight_allom]{weight_allom()}} 30 | function to determine the sample-size related weights attributed to 31 | equations without a specified sample size. Default is 0.1.} 32 | 33 | \item{w95}{a numeric vector, this parameter is used to determine the value at 34 | which the sample-size-related weight reaches 95\% of its maximum value 35 | (max=1). Default is 500.} 36 | } 37 | \value{ 38 | A named "numeric" vector with one weight for each equation. 39 | } 40 | \description{ 41 | This function attributes a weight to each equation based on its sampling 42 | size, and taxonomic and climatic similarity with the species/site combination 43 | considered. 44 | } 45 | \details{ 46 | Each equation is given a weight by the function \code{\link[=weight_allom]{weight_allom()}}, calculated 47 | as the product of the following components: 48 | 49 | (1) sample-size weight, calculated as: 50 | 51 | \deqn{1-exp(-n*(log(20)/w95))} 52 | 53 | where n is the sample size of the equation; the weight given to equations 54 | with no sample size information is determined by argument \code{wna} (0.1 by 55 | default). 56 | 57 | (2) climate weight, based on the similarity between the climatic conditions 58 | of the equation site and the target location, using the three-letter system 59 | of Koppen's climate scheme. Climate weights associated with each combination 60 | of two Koppen climates are provided in \code{data("koppenMatrix")}. The resulting 61 | weight has a value between 1e-6 (different climate groups) and 1 (exactly the 62 | same climate classification). When an equation was calibrated with trees from 63 | several locations with different Koppen climates, the maximum value out of 64 | all pairwise equation-site climate weights is used. 65 | 66 | (3) taxonomic weight: equal to 1 for same species equations, 0.8 for same 67 | genus equations, 0.5 for same family equations and for equations calibrated 68 | for the same broad functional or taxonomic group (e.g. shrubs, conifers, 69 | angiosperms). All other equations are given a low taxonomic weight of 1e-6: 70 | these equations will have a significant relative weight in the final 71 | prediction only when no other more specific equation is available. 72 | } 73 | \examples{ 74 | x <- weight_allom( 75 | genus = "Acer", 76 | species = "negundo", 77 | coords = c(-78.2, 38.9) 78 | ) 79 | str(x) 80 | head(x) 81 | } 82 | \seealso{ 83 | \code{\link[=get_biomass]{get_biomass()}}, \code{\link[=new_equations]{new_equations()}}. 84 | } 85 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(allodb) 3 | 4 | test_check("allodb") 5 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/FIXME.md: -------------------------------------------------------------------------------- 1 | # with bad `new_unit_dbh` throws no error 2 | 3 | `new_unit_dbh` must be in 'cm', 'mm' or 'inch'. 4 | 5 | # with bad `new_unit_output` throws no error 6 | 7 | `new_unit_output` must be 'g', 'kg', 'Mg' or 'lbs', or 'm'. 8 | 9 | -------------------------------------------------------------------------------- /tests/testthat/_snaps/new_equations.md: -------------------------------------------------------------------------------- 1 | # w/ `new_taxa` and `NULL` `new_allometry` errors gracefully 2 | 3 | `new_allometry` must not be `NULL` 4 | i Did you forget to add the new allometry? 5 | 6 | # with `new_allometry` and NULL `new_taxa` errors gracefully 7 | 8 | You must provide the taxa, coordinates, DBH range 9 | and sample size of you new allometries. 10 | 11 | # with a `new_coords` 'matrix' 2x1 errors gracefully 12 | 13 | `coords` must be a numeric vector or matrix, with 2 values or columns. 14 | 15 | # with arguments of different lenght errors gracefully 16 | 17 | All of these arguments must have the same length: 18 | * `new_taxa` 19 | * `new_allometry` 20 | * `new_min_dbh` 21 | * `new_max_dbh` 22 | * `new_sample_size` 23 | 24 | --- 25 | 26 | All of these arguments must have the same length: 27 | * `new_taxa` 28 | * `new_allometry` 29 | * `new_min_dbh` 30 | * `new_max_dbh` 31 | * `new_sample_size` 32 | 33 | --- 34 | 35 | All of these arguments must have the same length: 36 | * `new_taxa` 37 | * `new_allometry` 38 | * `new_min_dbh` 39 | * `new_max_dbh` 40 | * `new_sample_size` 41 | 42 | --- 43 | 44 | All of these arguments must have the same length: 45 | * `new_taxa` 46 | * `new_allometry` 47 | * `new_min_dbh` 48 | * `new_max_dbh` 49 | * `new_sample_size` 50 | 51 | # if `new_allometry` isn't of type character errors gracefully 52 | 53 | The equation allometry should be a character vector. 54 | 55 | # if `new_allometry` conains an assignment errors gracefully 56 | 57 | `new_allometry` must be a function of dbh (e.g. '0.5 * dbh^2'). 58 | 59 | --- 60 | 61 | `new_allometry` must be a function of dbh (e.g. '0.5 * dbh^2'). 62 | 63 | # height must be in meters 64 | 65 | Height allometries outputs must be in 'm'. 66 | 67 | --- 68 | 69 | Height allometries outputs must be in 'm'. 70 | 71 | # with bad coordinates errors gracefully 72 | 73 | Longitude must be between -180 and 180, and latitude between 90 and 0. 74 | 75 | # with equation not a function of DBH errors gracefully 76 | 77 | Each new allometry must contain DBH as a dependent variable. 78 | 79 | -------------------------------------------------------------------------------- /tests/testthat/test-FIXME.R: -------------------------------------------------------------------------------- 1 | # These tests characterize odd behaviour we need to discuss and maybe FIXME 2 | 3 | test_that("w/ `NULL` `new_taxa`, `new_allometry`, and `new_coords, outputs 4 | identical to `new_equations()` -- with all defaults", { 5 | # Avoid unimportant differences in attributes 6 | mini_attr <- function(data) { 7 | mini <- names(attributes(data.frame(x = 1))) 8 | full <- names(attributes(data)) 9 | extra <- setdiff(full, mini) 10 | 11 | for (i in seq_along(extra)) { 12 | attr(data, extra[[i]]) <- NULL 13 | } 14 | 15 | data 16 | } 17 | 18 | out <- new_equations( 19 | new_taxa = NULL, 20 | new_allometry = NULL, 21 | new_coords = NULL, 22 | new_min_dbh = 5, 23 | new_max_dbh = 50, 24 | new_sample_size = 50 25 | ) 26 | 27 | expect_equal(mini_attr(out), mini_attr(new_equations())) 28 | }) 29 | 30 | test_that("w/ all defaults, it's insensitive to `new_min_dbh`, `new_max_dbh`, 31 | and `new_sample_size`", { 32 | expect_equal( 33 | new_equations(new_min_dbh = 111, new_max_dbh = 111, new_sample_size = 111), 34 | new_equations(new_min_dbh = 999, new_max_dbh = 999, new_sample_size = 999) 35 | ) 36 | }) 37 | 38 | test_that("w/ non-numeric values passed to new_min_dbh, new_max_dbh, 39 | new_sample_size it throws no error", { 40 | # The body of `new_equations()` includes an error that seems to not work 41 | none <- NA 42 | expect_error(new_equations(new_min_dbh = "a"), none) 43 | expect_error(new_equations(new_max_dbh = "a"), none) 44 | expect_error(new_equations(new_sample_size = "a"), none) 45 | }) 46 | 47 | test_that("outputs a dataframe of unstable structure", { 48 | # When the output of a function is unstable, it's hard to program with it. 49 | # Best is to ensure the output has always the same number of columns (unless 50 | # it's a function which goal is to change the number of columns, e.g. 51 | # `subset()`). 52 | out1 <- new_equations( 53 | new_taxa = "Faga", 54 | new_allometry = "exp(-2+log(dbh)*2.5)", 55 | new_coords = c(-0.07, 46.11), 56 | new_min_dbh = 5, 57 | new_max_dbh = 50, 58 | new_sample_size = 50 59 | ) 60 | 61 | out2 <- new_equations( 62 | new_min_dbh = 5, 63 | new_max_dbh = 50, 64 | new_sample_size = 50 65 | ) 66 | 67 | expect_false(identical(ncol(out1), ncol(out2))) 68 | }) 69 | 70 | test_that("with bad `new_unit_dbh` throws no error", { 71 | # Arguments interact with each other. This error does not work when 72 | # new_equations() is called with defaults, but does work when it's passed 73 | # some values 74 | 75 | # Unexpected: Error doesn't throw 76 | FIXME_none <- NA 77 | expect_error(new_equations(new_unit_dbh = "bad "), FIXME_none) 78 | 79 | # Eexpected: Error throws 80 | expect_snapshot_error( 81 | new_equations( 82 | new_unit_dbh = "bad ", 83 | new_taxa = "Faga", 84 | new_allometry = "exp(-2+log(dbh)*2.5)", 85 | new_coords = c(-0.07, 46.11), 86 | new_min_dbh = 5, 87 | new_max_dbh = 50, 88 | new_sample_size = 50 89 | ) 90 | ) 91 | }) 92 | 93 | test_that("with bad `new_unit_output` throws no error", { 94 | # Unexpected: Error doesn't throw 95 | FIXME_none <- NA 96 | expect_error(new_equations(new_unit_output = "bad "), FIXME_none) 97 | 98 | # Eexpected: Error throws 99 | expect_snapshot_error( 100 | new_equations( 101 | new_unit_output = "bad ", 102 | new_taxa = "Faga", 103 | new_allometry = "exp(-2+log(dbh)*2.5)", 104 | new_coords = c(-0.07, 46.11), 105 | new_min_dbh = 5, 106 | new_max_dbh = 50, 107 | new_sample_size = 50 108 | ) 109 | ) 110 | }) 111 | 112 | test_that("height can be anything", { 113 | bad <- "BAD" 114 | none <- NA 115 | expect_error( 116 | new_equations(new_output_var = "Height", new_unit_output = bad), 117 | none 118 | ) 119 | }) 120 | -------------------------------------------------------------------------------- /tests/testthat/test-data.R: -------------------------------------------------------------------------------- 1 | test_that("all dataframes are also tibbles", { 2 | nms <- utils::data(package = "allodb")$results[, "Item"] 3 | datasets <- lapply(nms, function(x) get(x, "package:allodb")) 4 | datasets <- setNames(datasets, nms) 5 | is_dataframe <- unlist(lapply(datasets, is.data.frame)) 6 | dataframes <- datasets[is_dataframe] 7 | 8 | expect_true(all(unlist(lapply(dataframes, tibble::is_tibble)))) 9 | }) 10 | -------------------------------------------------------------------------------- /tests/testthat/test-equations.R: -------------------------------------------------------------------------------- 1 | test_that("all equations are lowercase", { 2 | expect_equal( 3 | allodb::equations$equation_allometry, 4 | tolower(allodb::equations$equation_allometry) 5 | ) 6 | }) 7 | 8 | test_that("all equations are valid", { 9 | no_error <- NA 10 | expect_error(validate_equations(equations$equation_allometry), no_error) 11 | }) 12 | -------------------------------------------------------------------------------- /tests/testthat/test-est_params.R: -------------------------------------------------------------------------------- 1 | test_that("est_params() returns a dataframe with all 2 | combinations of species x locations", { 3 | test_tab <- allodb::scbi_stem1[1:50, ] 4 | test_tab$site <- sample(2, 50, TRUE) 5 | sites <- 6 | data.frame( 7 | stringsAsFactors = FALSE, site = 1:2, 8 | long = c(-78, -85), lat = c(40, 45) 9 | ) 10 | test_tab <- merge(test_tab, sites, by = "site") 11 | ncombi <- nrow(unique(test_tab[, c("genus", "species", "site")])) 12 | testall <- est_params( 13 | genus = test_tab$genus, 14 | species = test_tab$species, 15 | coords = test_tab[, c("long", "lat")] 16 | ) 17 | expect_s3_class(testall, "data.frame") 18 | expect_equal(nrow(testall), ncombi) 19 | expect_equal(ncol(testall), 7) 20 | }) 21 | 22 | test_that("est_params can be used with a new equation table", { 23 | expect_s3_class( 24 | est_params( 25 | genus = c("Quercus", "Fagus"), 26 | coords = c(-78, 40), 27 | new_eqtable = new_equations(subset_taxa = "Quercus") 28 | ), 29 | "data.frame" 30 | ) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test-get_biomass.R: -------------------------------------------------------------------------------- 1 | test_that("get_biomass works with genus and species 2 | information and provides reasonable outputs", { 3 | expect_equal( 4 | get_biomass( 5 | dbh = 20, 6 | genus = "Quercus", 7 | species = "alba", 8 | coords = c(-78, 40) 9 | ), 10 | 240, 11 | tolerance = 50 12 | ) 13 | expect_equal( 14 | get_biomass( 15 | dbh = 20, 16 | genus = "Quercus", 17 | coords = c(-78, 40) 18 | ), 19 | 240, 20 | tolerance = 50 21 | ) 22 | }) 23 | 24 | test_that("weighting parameters can be easily changed 25 | without changing results dramatically", { 26 | expect_equal( 27 | get_biomass( 28 | dbh = 20, 29 | genus = "Quercus", 30 | coords = c(-78, 40), 31 | wna = 0.01, 32 | w95 = 1000 33 | ), 34 | 240, 35 | tolerance = 50 36 | ) 37 | }) 38 | 39 | test_that("get_biomass returns zero when dbh = 0 and NA when dbh = NA", { 40 | expect_equal(get_biomass( 41 | dbh = 0, 42 | genus = "Quercus", 43 | coords = c(-78, 40) 44 | ), 0) 45 | expect_equal( 46 | get_biomass( 47 | dbh = NA, 48 | genus = "Quercus", 49 | coords = c(-78, 40) 50 | ), 51 | NA_integer_ 52 | ) 53 | }) 54 | 55 | test_that("get_biomass returns an error message when dbh values are < 0, > 1000, 56 | or when coordinates are not in their expected range", { 57 | expect_error(get_biomass( 58 | dbh = -10, 59 | genus = "Quercus", 60 | coords = c(-78, 40) 61 | )) 62 | expect_error(get_biomass( 63 | dbh = 10, 64 | genus = "Quercus", 65 | coords = c(-190, 40) 66 | )) 67 | expect_error(get_biomass( 68 | dbh = 10, 69 | genus = "Quercus", 70 | coords = c(-78, 100) 71 | )) 72 | }) 73 | 74 | test_that("get_biomass accepts new equation table", { 75 | expect_equal( 76 | get_biomass( 77 | dbh = 20, 78 | genus = "Quercus", 79 | coords = c(-78, 40), 80 | new_eqtable = new_equations(subset_taxa = "Quercus") 81 | ), 82 | 240, 83 | tolerance = 50 84 | ) 85 | }) 86 | 87 | test_that("get_biomass can be used for several individuals and sites", { 88 | inds_1site <- get_biomass( 89 | dbh = c(20, 40, 10), 90 | genus = c("Quercus", "Acer", "Fagus"), 91 | coords = c(-78, 40) 92 | ) 93 | inds_2site <- get_biomass( 94 | dbh = c(20, 40, 10), 95 | genus = c("Quercus", "Acer", "Fagus"), 96 | coords = rbind( 97 | c(-78, 40), 98 | c(-78, 40), 99 | c(-85, 45) 100 | ) 101 | ) 102 | expect_equal(inds_1site, c(240, 1500, 50), tolerance = 50) 103 | expect_equal(inds_2site, c(240, 1500, 50), tolerance = 50) 104 | }) 105 | 106 | test_that("get_biomass gives stable results when run several 107 | times with the same inputs", { 108 | run_1 <- 109 | get_biomass( 110 | dbh = 20, 111 | genus = "Quercus", 112 | coords = c(-78, 40) 113 | ) 114 | run_2 <- 115 | get_biomass( 116 | dbh = 20, 117 | genus = "Quercus", 118 | coords = c(-78, 40) 119 | ) 120 | expect_equal(run_1, run_2) 121 | }) 122 | 123 | test_that("biomass estimates for one individual do not 124 | depend on other measurements", { 125 | agb_alone <- 126 | get_biomass( 127 | dbh = 20, 128 | genus = "Quercus", 129 | coords = c(-78, 40) 130 | ) 131 | agb_withfagus <- 132 | get_biomass( 133 | dbh = c(20, 10), 134 | genus = c("Quercus", "Fagus"), 135 | coords = c(-78, 40) 136 | )[1] 137 | expect_equal(agb_alone, agb_withfagus) 138 | }) 139 | 140 | test_that("get_biomass gives error message when inputs are 141 | not the same length", { 142 | expect_error(get_biomass( 143 | dbh = c(20, 10, 30), 144 | genus = c("Quercus", "Fagus"), 145 | coords = c(-78, 40) 146 | )) 147 | }) 148 | -------------------------------------------------------------------------------- /tests/testthat/test-illustrate_allodb.R: -------------------------------------------------------------------------------- 1 | test_that("illustrate_allodb() returns a ggplot object", { 2 | expect_s3_class( 3 | illustrate_allodb( 4 | genus = "Quercus", 5 | coords = c(-78, 40) 6 | ), 7 | "ggplot" 8 | ) 9 | }) 10 | 11 | test_that("illustrate_allodb() accepts changes in the equation table used", { 12 | g <- illustrate_allodb( 13 | genus = "Quercus", 14 | coords = c(-78, 40) 15 | ) 16 | g2 <- illustrate_allodb( 17 | genus = "Quercus", 18 | coords = c(-78, 40), 19 | new_eqtable = new_equations( 20 | new_allometry = "0.12 * dbh ^ 2.5", 21 | new_taxa = "Quercus", 22 | new_coords = c(-80, 40), 23 | new_min_dbh = 5, 24 | new_max_dbh = 40, 25 | new_sample_size = 500 26 | ) 27 | ) 28 | expect_s3_class(g, "ggplot") 29 | expect_s3_class(g2, "ggplot") 30 | expect_true(any(grepl("new", g2$data$equation_id))) 31 | }) 32 | 33 | test_that("illustrate_allodb() accepts changes in the equation table used", { 34 | g <- illustrate_allodb( 35 | genus = "Quercus", 36 | coords = c(-78, 40), 37 | new_eqtable = new_equations(subset_taxa = "Quercus") 38 | ) 39 | g2 <- illustrate_allodb( 40 | genus = "Quercus", 41 | coords = c(-78, 40), 42 | new_eqtable = new_equations( 43 | new_allometry = "0.12 * dbh ^ 2.5", 44 | new_taxa = "Quercus", 45 | new_coords = c(-80, 40), 46 | new_min_dbh = 5, 47 | new_max_dbh = 40, 48 | new_sample_size = 500 49 | ) 50 | ) 51 | expect_s3_class(g, "ggplot") 52 | expect_s3_class(g2, "ggplot") 53 | expect_true(any(grepl("new", g2$data$equation_id))) 54 | }) 55 | 56 | test_that("The top neq equations are displayed", { 57 | g <- 58 | illustrate_allodb( 59 | genus = "Quercus", 60 | coords = c(-78, 40), 61 | neq = 15 62 | ) 63 | tab <- data.frame(stringsAsFactors = FALSE, table(equation_id = g$data$equation_id)) 64 | tab <- tab[order(tab$Freq, decreasing = TRUE), ] 65 | topfreq <- tab$equation_id[1:15] 66 | legeq <- 67 | vapply(strsplit(levels(g$data$equation), " - "), function(x) { 68 | x[1] 69 | }, FUN.VALUE = "x") 70 | 71 | expect_s3_class(g, "ggplot") 72 | expect_true(all(topfreq %in% legeq)) 73 | }) 74 | 75 | test_that("The option logxy = TRUE displays graphs with log scale", { 76 | g <- illustrate_allodb( 77 | genus = "Quercus", 78 | coords = c(-78, 40), 79 | logxy = TRUE 80 | ) 81 | expect_s3_class(g, "ggplot") 82 | }) 83 | -------------------------------------------------------------------------------- /tests/testthat/test-new_equations.R: -------------------------------------------------------------------------------- 1 | test_that("new_equations() returns a dataframe with all 2 | necessary information", { 3 | tab <- new_equations() 4 | expect_s3_class(tab, "data.frame") 5 | expect_type(tab$equation_id, "character") 6 | expect_type(tab$equation_taxa, "character") 7 | expect_type(tab$equation_allometry, "character") 8 | expect_type(tab$independent_variable, "character") 9 | expect_type(tab$dependent_variable, "character") 10 | expect_type(tab$koppen, "character") 11 | expect_type(tab$dbh_min_cm, "double") 12 | expect_type(tab$dbh_max_cm, "double") 13 | expect_type(tab$sample_size, "double") 14 | expect_type(tab$dbh_units_original, "character") 15 | expect_type(tab$output_units_original, "character") 16 | }) 17 | 18 | test_that("new_equations() can be subsetted by taxa", { 19 | subset_taxa <- new_equations(subset_taxa = c("Quercus", "Acer")) 20 | cols <- c( 21 | "equation_id", 22 | "equation_taxa", 23 | "equation_allometry", 24 | "independent_variable", 25 | "dependent_variable", 26 | "koppen", 27 | "dbh_min_cm", 28 | "dbh_max_cm", 29 | "sample_size", 30 | "dbh_units_original", 31 | "output_units_original" 32 | ) 33 | expect_s3_class(subset_taxa, "data.frame") 34 | expect_true(all(cols %in% colnames(new_equations()))) 35 | expect_true(all(grepl( 36 | "Quercus|Acer", subset_taxa$equation_taxa 37 | ))) 38 | }) 39 | 40 | test_that("new_equations() can be subsetted by climate", { 41 | subset_koppen <- new_equations(subset_climate = "Csb") 42 | cols <- c( 43 | "equation_id", 44 | "equation_taxa", 45 | "equation_allometry", 46 | "independent_variable", 47 | "dependent_variable", 48 | "koppen", 49 | "dbh_min_cm", 50 | "dbh_max_cm", 51 | "sample_size", 52 | "dbh_units_original", 53 | "output_units_original" 54 | ) 55 | expect_s3_class(subset_koppen, "data.frame") 56 | expect_true(all(cols %in% colnames(subset_koppen))) 57 | expect_true(all(grepl("Csb", subset_koppen$koppen))) 58 | }) 59 | 60 | test_that("new_equations() can be subsetted by geographic region", { 61 | subset_geo <- new_equations(subset_region = "Europe") 62 | cols <- c( 63 | "equation_id", 64 | "equation_taxa", 65 | "equation_allometry", 66 | "independent_variable", 67 | "dependent_variable", 68 | "koppen", 69 | "dbh_min_cm", 70 | "dbh_max_cm", 71 | "sample_size", 72 | "dbh_units_original", 73 | "output_units_original" 74 | ) 75 | expect_s3_class(subset_geo, "data.frame") 76 | expect_true(all(cols %in% colnames(subset_geo))) 77 | expect_true(all(grepl("Europe", subset_geo$geographic_area))) 78 | }) 79 | 80 | test_that("new_equations() can be subsetted by equation id", { 81 | ids <- c("13b352", "9c4cc9", "55476a", "74c518", "cde8d1") 82 | subset_id <- new_equations(subset_ids = ids) 83 | cols <- c( 84 | "equation_id", 85 | "equation_taxa", 86 | "equation_allometry", 87 | "independent_variable", 88 | "dependent_variable", 89 | "koppen", 90 | "dbh_min_cm", 91 | "dbh_max_cm", 92 | "sample_size", 93 | "dbh_units_original", 94 | "output_units_original" 95 | ) 96 | expect_s3_class(subset_id, "data.frame") 97 | expect_true(all(cols %in% colnames(subset_id))) 98 | expect_true(all(subset_id$equation_id %in% ids)) 99 | }) 100 | 101 | test_that("new_equations() can be subsetted by type of output", { 102 | subset_h <- new_equations(subset_output = "Height") 103 | cols <- c( 104 | "equation_id", 105 | "equation_taxa", 106 | "equation_allometry", 107 | "independent_variable", 108 | "dependent_variable", 109 | "koppen", 110 | "dbh_min_cm", 111 | "dbh_max_cm", 112 | "sample_size", 113 | "dbh_units_original", 114 | "output_units_original" 115 | ) 116 | expect_s3_class(subset_h, "data.frame") 117 | expect_true(all(cols %in% colnames(subset_h))) 118 | expect_true(all(grepl("Height", subset_h$dependent_variable))) 119 | }) 120 | 121 | test_that( 122 | "equations can be added to the equation dataframe and then 123 | used in the get_biomass function", 124 | { 125 | all_eqtab <- 126 | new_equations( 127 | new_taxa = c("Quercus ilex", "Castanea sativa"), 128 | new_allometry = c("0.12 * dbh ^ 2.5", "0.15*dbh^2.7"), 129 | new_coords = c(4, 44), 130 | new_min_dbh = c(5, 10), 131 | new_max_dbh = c(35, 68), 132 | new_sample_size = c(143, 62) 133 | ) 134 | new_eq <- subset(all_eqtab, grepl("new", equation_id)) 135 | expect_s3_class(new_eq, "data.frame") 136 | expect_equal(nrow(new_eq), 2) 137 | 138 | agb1 <- 139 | get_biomass( 140 | dbh = 20, 141 | genus = "Quercus", 142 | coords = c(-78, 40), 143 | new_eqtable = all_eqtab 144 | ) 145 | agb2 <- 146 | get_biomass( 147 | dbh = 20, 148 | genus = "Quercus", 149 | coords = c(-78, 40), 150 | new_eqtable = new_eq 151 | ) 152 | expect_equal(agb1, 240, tolerance = 50) 153 | expect_equal(agb2, 240, tolerance = 50) 154 | } 155 | ) 156 | 157 | test_that("equations cannot be added when the input format is not correct", { 158 | expect_error( 159 | new_equations( 160 | new_taxa = "Quercus ilex", 161 | new_allometry = "0.12 * dbh ^ 2.5", 162 | new_coords = c(4, 44), 163 | new_minDBH = c(5, 10), 164 | new_maxDBH = 35, 165 | new_sampleSize = 143 166 | ) 167 | ) 168 | expect_error( 169 | new_equations( 170 | new_taxa = "Quercus ilex", 171 | new_coords = c(4, 44), 172 | new_minDBH = 5, 173 | new_maxDBH = 35, 174 | new_sampleSize = 143 175 | ) 176 | ) 177 | expect_error( 178 | new_equations( 179 | new_taxa = "Quercus ilex", 180 | new_allometry = "agb = 0.12 * dbh ^ 2.5", 181 | new_coords = c(4, 44), 182 | new_minDBH = 5, 183 | new_maxDBH = 35, 184 | new_sampleSize = 143 185 | ) 186 | ) 187 | expect_error( 188 | new_equations( 189 | new_taxa = "Quercus ilex", 190 | new_allometry = "0.12 * dbh ^ 2.5*", 191 | new_coords = c(4, 44), 192 | new_minDBH = 5, 193 | new_maxDBH = 35, 194 | new_sampleSize = 143 195 | ) 196 | ) 197 | expect_error( 198 | new_equations( 199 | new_taxa = "Quercus ilex", 200 | new_allometry = "0.12 * dbh ^ 2.5", 201 | new_coords = c(4, 44), 202 | new_minDBH = 5, 203 | new_maxDBH = 35, 204 | new_sampleSize = "143" 205 | ) 206 | ) 207 | expect_error( 208 | new_equations( 209 | new_taxa = "Quercus ilex", 210 | new_allometry = "0.12 * dbh ^ 2.5", 211 | new_coords = 44, 212 | new_minDBH = 5, 213 | new_maxDBH = 35, 214 | new_sampleSize = 143 215 | ) 216 | ) 217 | }) 218 | 219 | test_that("w/ `new_taxa` and `NULL` `new_allometry` errors gracefully", { 220 | new_taxa <- "Faga" 221 | expect_snapshot_error( 222 | new_equations( 223 | new_taxa = new_taxa, 224 | new_allometry = NULL, 225 | new_coords = c(-0.07, 46.11), 226 | new_min_dbh = 5, 227 | new_max_dbh = 50, 228 | new_sample_size = 50 229 | ) 230 | ) 231 | }) 232 | 233 | # FIXME: The same applies for a bunch of other arguments, and testing each 234 | # combination seems tedious. This suggests a problem in the design. 235 | test_that("with `new_allometry` and NULL `new_taxa` errors gracefully", { 236 | expect_snapshot_error(new_equations(new_allometry = "a", new_taxa = NULL)) 237 | }) 238 | 239 | test_that("with a `new_coords` 'matrix' 1x2 works", { 240 | nrow <- 1 241 | ncol <- 2 242 | a_matrix <- matrix(c(-0.07, 46.11), ncol = ncol) 243 | no_error <- NA 244 | expect_error( 245 | new_equations( 246 | new_taxa = "Faga", 247 | new_allometry = "exp(-2+log(dbh)*2.5)", 248 | new_coords = a_matrix, 249 | new_min_dbh = 5, 250 | new_max_dbh = 50, 251 | new_sample_size = 50 252 | ), 253 | no_error 254 | ) 255 | }) 256 | 257 | test_that("with a `new_coords` 'matrix' 2x1 errors gracefully", { 258 | nrow <- 2 259 | ncol <- 1 260 | a_matrix <- matrix(c(-0.07, 46.11), ncol = ncol) 261 | expect_snapshot_error( 262 | new_equations( 263 | new_taxa = "Faga", 264 | new_allometry = "exp(-2+log(dbh)*2.5)", 265 | new_coords = a_matrix, 266 | new_min_dbh = 5, 267 | new_max_dbh = 50, 268 | new_sample_size = 50 269 | ) 270 | ) 271 | }) 272 | 273 | test_that("with arguments of different lenght errors gracefully", { 274 | too_long <- c("exp(-2+log(dbh)*2.5)", "exp(-2+log(dbh)*2.5)") 275 | expect_snapshot_error( 276 | new_equations( 277 | new_taxa = "Faga", 278 | new_allometry = too_long, 279 | new_coords = c(-0.07, 46.11), 280 | new_min_dbh = 5, 281 | new_max_dbh = 50, 282 | new_sample_size = 50 283 | ) 284 | ) 285 | 286 | too_long <- c(5, 5) 287 | expect_snapshot_error( 288 | new_equations( 289 | new_taxa = "Faga", 290 | new_allometry = "exp(-2+log(dbh)*2.5)", 291 | new_coords = c(-0.07, 46.11), 292 | new_min_dbh = too_long, 293 | new_max_dbh = 50, 294 | new_sample_size = 50 295 | ) 296 | ) 297 | 298 | too_long <- c(50, 50) 299 | expect_snapshot_error( 300 | new_equations( 301 | new_taxa = "Faga", 302 | new_allometry = "exp(-2+log(dbh)*2.5)", 303 | new_coords = c(-0.07, 46.11), 304 | new_min_dbh = 5, 305 | new_max_dbh = too_long, 306 | new_sample_size = 50 307 | ) 308 | ) 309 | 310 | too_long <- c(50, 50) 311 | expect_snapshot_error( 312 | new_equations( 313 | new_taxa = "Faga", 314 | new_allometry = "exp(-2+log(dbh)*2.5)", 315 | new_coords = c(-0.07, 46.11), 316 | new_min_dbh = 5, 317 | new_max_dbh = 50, 318 | new_sample_size = too_long 319 | ) 320 | ) 321 | }) 322 | 323 | test_that("if `new_allometry` isn't of type character errors gracefully", { 324 | not_character <- 1 325 | expect_snapshot_error( 326 | new_equations( 327 | new_taxa = "Faga", 328 | new_allometry = not_character, 329 | new_coords = c(-0.07, 46.11), 330 | new_min_dbh = 5, 331 | new_max_dbh = 50, 332 | new_sample_size = 50 333 | ) 334 | ) 335 | }) 336 | 337 | test_that("if `new_allometry` conains an assignment errors gracefully", { 338 | has_assignment <- "a = 1" 339 | expect_snapshot_error( 340 | new_equations( 341 | new_taxa = "Faga", 342 | new_allometry = has_assignment, 343 | new_coords = c(-0.07, 46.11), 344 | new_min_dbh = 5, 345 | new_max_dbh = 50, 346 | new_sample_size = 50 347 | ) 348 | ) 349 | 350 | has_assignment <- "a <- 1" 351 | expect_snapshot_error( 352 | new_equations( 353 | new_taxa = "Faga", 354 | new_allometry = has_assignment, 355 | new_coords = c(-0.07, 46.11), 356 | new_min_dbh = 5, 357 | new_max_dbh = 50, 358 | new_sample_size = 50 359 | ) 360 | ) 361 | }) 362 | 363 | test_that("height must be in meters", { 364 | bad <- "g" 365 | expect_snapshot_error( 366 | new_equations( 367 | new_output_var = "Height", 368 | new_unit_output = bad, 369 | new_taxa = "Faga", 370 | new_allometry = "dbh", 371 | new_coords = c(-0.07, 46.11), 372 | new_min_dbh = 5, 373 | new_max_dbh = 50, 374 | new_sample_size = 50 375 | ) 376 | ) 377 | }) 378 | 379 | test_that("height must be in meters", { 380 | bad <- "g" 381 | expect_snapshot_error( 382 | new_equations( 383 | new_output_var = "Height", 384 | new_unit_output = bad, 385 | new_taxa = "Faga", 386 | new_allometry = "dbh", 387 | new_coords = c(-0.07, 46.11), 388 | new_min_dbh = 1, 389 | new_max_dbh = 2, 390 | new_sample_size = 50 391 | ) 392 | ) 393 | }) 394 | 395 | test_that("with bad coordinates errors gracefully", { 396 | bad <- c(-999, 999) 397 | expect_snapshot_error( 398 | new_equations( 399 | new_taxa = "Faga", 400 | new_allometry = "dbh", 401 | new_coords = bad, 402 | new_min_dbh = 1, 403 | new_max_dbh = 2, 404 | new_sample_size = 50 405 | ) 406 | ) 407 | }) 408 | 409 | test_that("with equation not a function of DBH errors gracefully", { 410 | bad <- "1" 411 | expect_snapshot_error( 412 | new_equations( 413 | new_taxa = "Faga", 414 | new_allometry = bad, 415 | new_coords = c(0, 0), 416 | new_min_dbh = 1, 417 | new_max_dbh = 2, 418 | new_sample_size = 50 419 | ) 420 | ) 421 | }) 422 | 423 | # TODO: Continue to test that you get the expected errors 424 | -------------------------------------------------------------------------------- /tests/testthat/test-resample_agb.R: -------------------------------------------------------------------------------- 1 | test_that("resample_agb returns a dataframe of size 1e6 x 3", { 2 | res_test <- 3 | resample_agb( 4 | genus = "Quercus", 5 | species = "alba", 6 | coords = c(-78, 40) 7 | ) 8 | expect_s3_class(res_test, "data.frame") 9 | expect_equal(nrow(res_test), 1e6, tolerance = 1e2) 10 | expect_equal(ncol(res_test), 3) 11 | expect_type(res_test$equation_id, "character") 12 | expect_type(res_test$dbh, "double") 13 | expect_type(res_test$agb, "double") 14 | }) 15 | 16 | test_that( 17 | "resample_agb returns an error message when more than one 18 | taxon/location are used at once", 19 | { 20 | expect_error(resample_agb( 21 | genus = c("Fagus", "Quercus"), 22 | coords = c(-78, 40) 23 | )) 24 | expect_error(resample_agb( 25 | genus = c("Fagus"), coords = 26 | rbind(c(-78, 40), c(-85, 45)) 27 | )) 28 | } 29 | ) 30 | 31 | test_that("resample_agb can be used with a new equation table", { 32 | expect_s3_class( 33 | resample_agb( 34 | genus = "Quercus", 35 | coords = c(-78, 40), 36 | new_eqtable = new_equations(subset_taxa = "Quercus") 37 | ), 38 | "data.frame" 39 | ) 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-validate_equation.R: -------------------------------------------------------------------------------- 1 | test_that("with valid equations returns `equations` argument invisibly", { 2 | valid <- c("dbh + 1", "h + 1") 3 | no_error <- NA 4 | out <- expect_error(validate_equations(valid), no_error) 5 | expect_equal(out, valid) 6 | }) 7 | 8 | test_that("with invalid equations throwns an error", { 9 | invalid <- c("dbh + 1", "h + bad") 10 | expect_error(validate_equations(invalid), "bad.*not found") 11 | }) 12 | -------------------------------------------------------------------------------- /tests/testthat/test-weight_allom.R: -------------------------------------------------------------------------------- 1 | test_that("weight_allom returns a vector of the same length 2 | as the equation table.", { 3 | newtab <- new_equations(subset_taxa = "Quercus") 4 | weight_test <- weight_allom( 5 | genus = "Quercus", 6 | species = "alba", 7 | coords = c(-78, 40), 8 | new_eqtable = newtab 9 | ) 10 | expect_type(weight_test, "double") 11 | expect_equal(length(weight_test), nrow(newtab)) 12 | expect_true(all(names(weight_test) %in% newtab$equation_id)) 13 | }) 14 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/allodb.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Using allodb to estimate aboveground biomass" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Using allodb to estimate aboveground biomass} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>", 14 | echo = TRUE 15 | ) 16 | ``` 17 | 18 | ## Installation 19 | 20 | Install the development version of _allodb_ from GitHub: 21 | 22 | ```{r install, eval=FALSE} 23 | # install.packages("pak") 24 | pak::pak("ropensci/allodb") 25 | ``` 26 | 27 | ## Load the census data 28 | 29 | Prior to calculating tree biomass using _allodb_, users need to provide a table (i.e. dataframe) with DBH (cm), parsed species Latin names, and site(s) coordinates. In the following examples we use data from the Smithsonian Conservation Biology Institute, USA (SCBI) ForestGEO dynamics plot (1st census in 2008, trees from 1 hectare). Data can be requested through the ForestGEO portal (https://forestgeo.si.edu/) 30 | 31 | ```{r load-census-data} 32 | require(allodb) 33 | data(scbi_stem1) 34 | str(scbi_stem1) 35 | ``` 36 | 37 | ## Load and modify the equation table 38 | 39 | `allodb` provides a dataframe containing `r nrow(allodb::equations)` parsed allometric equations. 40 | 41 | ```{r load-equations} 42 | data(equations) 43 | ``` 44 | 45 | Additional information about the equation table can be found in the equation metadata. 46 | 47 | ```{r load-metadata} 48 | data(equations_metadata) 49 | ``` 50 | 51 | This equation table is the default in all functions of the package. Users can modify the set of equations that will be used to estimate biomass using the `new_equations()` function: users can work on a subset of those equations, or add new equations to the table (see `?allodb::new_equations`). The customized equation table should be provided as an argument in the `get_biomass()` (or other) function (argument name: `new_eqtable`). 52 | 53 | ### Subset the equation table 54 | 55 | ```{r subset-table} 56 | show_cols <- c("equation_id", "equation_taxa", "equation_allometry") 57 | eq_tab_acer <- new_equations(subset_taxa = "Acer") 58 | head(eq_tab_acer[, show_cols]) 59 | ``` 60 | 61 | ### Add new equations 62 | 63 | ```{r add-equations} 64 | eq_tab_add <- new_equations( 65 | new_taxa = c("Quercus ilex", "Castanea sativa"), 66 | new_allometry = c("0.12*dbh^2.5", "0.15*dbh^2.7"), 67 | new_coords = c(4, 44), 68 | new_min_dbh = c(5, 10), 69 | new_max_dbh = c(35, 68), 70 | new_sample_size = c(143, 62) 71 | ) 72 | ## show added equations - they contain "new" in their equation_id 73 | head(eq_tab_add[grepl("new", eq_tab_add$equation_id), ]) 74 | ``` 75 | 76 | 77 | ## Estimate the aboveground biomass 78 | 79 | The aboveground biomass (AGB) can be estimated using the `get_biomass()` function: the required arguments are the diameter at breast height (DBH, in cm), the taxonomic identification (to the genus or species level), and the location (long-lat coordinates). The output is the aboveground biomass of the tree in kg. 80 | 81 | ```{r calc-agb-poplar} 82 | get_biomass( 83 | dbh = 50, 84 | genus = "liriodendron", 85 | species = "tulipifera", 86 | coords = c(-78.2, 38.9) 87 | ) 88 | ``` 89 | 90 | The `get_biomass()` function can also be used to estimate the AGB of all trees in one (or several) censuses. 91 | 92 | ```{r calc-agb-all} 93 | scbi_stem1$agb <- 94 | get_biomass( 95 | dbh = scbi_stem1$dbh, 96 | genus = scbi_stem1$genus, 97 | species = scbi_stem1$species, 98 | coords = c(-78.2, 38.9) 99 | ) 100 | ``` 101 | 102 | ```{r plot-agb-scbi, fig.width = 6, fig.height = 5} 103 | plot( 104 | x = scbi_stem1$dbh, 105 | y = scbi_stem1$agb, 106 | col = factor(scbi_stem1$genus), 107 | xlab = "DBH (cm)", 108 | ylab = "AGB (kg)" 109 | ) 110 | ``` 111 | 112 | ## How AGB is estimated 113 | 114 | ### Attribute a weight to each equation in the equation table for each taxon/location combination 115 | 116 | Within the `get_biomass()` function, new allometric equations are calibrated for each taxon/location combinations in the user-provided dataframe. This is done by attributing a weight to each equation in the equation table, based on its sampling size, and taxonomic and climatic similarity with the taxon/location combination considered. 117 | 118 | ```{r weights} 119 | allom_weights <- 120 | weight_allom( 121 | genus = "Acer", 122 | species = "rubrum", 123 | coords = c(-78, 38) 124 | ) 125 | 126 | ## visualize weights 127 | equ_tab_acer <- new_equations() 128 | equ_tab_acer$weights <- allom_weights 129 | keep_cols <- 130 | c( 131 | "equation_id", 132 | "equation_taxa", 133 | "sample_size", 134 | "weights" 135 | ) 136 | order_weights <- order(equ_tab_acer$weights, decreasing = TRUE) 137 | equ_tab_acer <- equ_tab_acer[order_weights, keep_cols] 138 | head(equ_tab_acer) 139 | ``` 140 | 141 | ### Resample equations 142 | 143 | Equations are then resampled within their original DBH range: the number of resampled values for each equation is proportional to its weight (as attributed by the `weight_allom()` function). 144 | 145 | ```{r resample-acer, fig.width = 6, fig.height = 5} 146 | df_resample <- 147 | resample_agb( 148 | genus = "Acer", 149 | species = "rubrum", 150 | coords = c(-78, 38), 151 | nres = 1e4 152 | ) 153 | 154 | plot( 155 | df_resample$dbh, 156 | df_resample$agb, 157 | xlab = "DBH (cm)", 158 | ylab = "Resampled AGB values (kg)" 159 | ) 160 | ``` 161 | 162 | ### Calibrate a new equation for each taxon/location combination 163 | 164 | The resampled values are then used to fit the following nonlinear model: $AGB = a \cdot dbh ^ b + e$, with i.i.d. $e \sim \mathcal{N}(0, sigma^2)$. The parameters (_a_, _b_, and _sigma_) are returned by the `est_params()` function. In other words, this function calibrates new allometric equations from sampling previous ones. New allometric equations are calibrated for each species and location by resampling the original compiled equations; equations with a larger sample size, and/or higher taxonomic rank, and climatic similarity with the species and location in question are given a higher weight in this process. 165 | 166 | ```{r est-params-acer, fig.width = 6, fig.height = 5} 167 | pars_acer <- est_params( 168 | genus = "Acer", 169 | species = "rubrum", 170 | coords = c(-78, 38) 171 | ) 172 | plot( 173 | df_resample$dbh, 174 | df_resample$agb, 175 | xlab = "DBH (cm)", 176 | ylab = "Resampled AGB values (kg)" 177 | ) 178 | curve(pars_acer$a * x^pars_acer$b, 179 | add = TRUE, col = 2, lwd = 2 180 | ) 181 | ``` 182 | 183 | The `est_params()` function can be used for all species/site combinations in the dataset at once. 184 | 185 | ```{r est-params-all} 186 | params <- est_params( 187 | genus = scbi_stem1$genus, 188 | species = scbi_stem1$species, 189 | coords = c(-78.2, 38.9) 190 | ) 191 | head(params) 192 | ``` 193 | 194 | AGB is then recalculated as `AGB = a * dbh^b` within the `get_biomass()` function. 195 | 196 | ## Visualize the recalibration of equations 197 | 198 | The recalibrated equation for one taxon/location combination can be easily visualized with the `illustrate_allodb()` function, which returns a ggplot (see package `ggplot2`) with all resampled values, and the top equations used displayed in the legend. The user can control the number of equations and equation information shown in the legend. The red dotted line is the recalibrated equation used in the `get_biomass()` function. 199 | 200 | ```{r illustrate-allodb, fig.height = 4, fig.width=8} 201 | illustrate_allodb( 202 | genus = "Acer", 203 | species = "rubrum", 204 | coords = c(-78, 38) 205 | ) 206 | ``` 207 | 208 | ```{r illustrate-allodb2, fig.height = 5, fig.width=10} 209 | illustrate_allodb( 210 | genus = "Acer", 211 | species = "rubrum", 212 | coords = c(-78, 38), 213 | neq = 15, 214 | eqinfo = c("equation_taxa", "geographic_area") 215 | ) 216 | ``` 217 | --------------------------------------------------------------------------------