├── revdep ├── problems.md ├── .gitignore ├── failures.md └── README.md ├── .gitignore ├── .buildignore ├── .gitignore ├── fgeo-logo │ └── ForestGEO_logo.jpg ├── jobs.R ├── fgeo.Rmd └── eda.Rmd ├── tests ├── testthat.R ├── spelling.R └── testthat │ ├── test-zzz.R │ ├── test-fgeo_help.R │ └── test-fgeo_packages.R ├── inst ├── extdata │ ├── template-foreign.txt │ └── template-native.txt └── WORDLIST ├── man ├── figures │ ├── README-autoplot-sp-1.png │ ├── README-fgeo-downloads-1.png │ └── README-autoplot-sp-elev-1.png ├── pipe.Rd ├── fgeo_browse.Rd ├── fgeo_packages.Rd ├── fgeo_help.Rd └── fgeo-package.Rd ├── R ├── imports.R ├── utils-pipe.R ├── fgeo-package.R ├── zzz.R ├── fgeo_browse.R ├── utils.R ├── fgeo_help.R ├── attach.R ├── fgeo_packages.R └── conflicts.R ├── codecov.yml ├── NEWS.md ├── .Rbuildignore ├── fgeo.Rproj ├── .github ├── ISSUE_TEMPLATE.md ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── SUPPORT.md └── CONTRIBUTING.md ├── cran-comments.md ├── NAMESPACE ├── .travis.yml ├── appveyor.yml ├── _pkgdown.yml ├── vignettes └── siteonly │ ├── reference.Rmd │ ├── fgeo-1-2-0-release-candidate.Rmd │ └── questions-and-answers.Rmd ├── DESCRIPTION ├── README.Rmd ├── README.md └── LICENSE.md /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | -------------------------------------------------------------------------------- /.buildignore/.gitignore: -------------------------------------------------------------------------------- 1 | jobs1.R 2 | jobs2.R 3 | tmp.R 4 | -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !*.md 4 | !*.R 5 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(fgeo) 3 | 4 | test_check("fgeo") 5 | -------------------------------------------------------------------------------- /inst/extdata/template-foreign.txt: -------------------------------------------------------------------------------- 1 | #' @importFrom {package} {topic} 2 | #' @export 3 | {package}::{alias} 4 | -------------------------------------------------------------------------------- /man/figures/README-autoplot-sp-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestgeo/fgeo/HEAD/man/figures/README-autoplot-sp-1.png -------------------------------------------------------------------------------- /man/figures/README-fgeo-downloads-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestgeo/fgeo/HEAD/man/figures/README-fgeo-downloads-1.png -------------------------------------------------------------------------------- /.buildignore/fgeo-logo/ForestGEO_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestgeo/fgeo/HEAD/.buildignore/fgeo-logo/ForestGEO_logo.jpg -------------------------------------------------------------------------------- /man/figures/README-autoplot-sp-elev-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/forestgeo/fgeo/HEAD/man/figures/README-autoplot-sp-elev-1.png -------------------------------------------------------------------------------- /inst/extdata/template-native.txt: -------------------------------------------------------------------------------- 1 | # Source: {link} 2 | #' @inherit {package}::{alias} 3 | #' @export 4 | {alias} <- {package}::{alias} 5 | -------------------------------------------------------------------------------- /tests/spelling.R: -------------------------------------------------------------------------------- 1 | if (requireNamespace("spelling", quietly = TRUE)) { 2 | spelling::spell_check_test( 3 | vignettes = TRUE, error = FALSE, 4 | skip_on_cran = TRUE 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /R/imports.R: -------------------------------------------------------------------------------- 1 | #' @importFrom rlang .data %||% enquos 2 | #' @importFrom dplyr filter select mutate group_by ungroup arrange 3 | #' @importFrom glue glue 4 | NULL 5 | 6 | globalVariables(c(".")) 7 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /tests/testthat/test-zzz.R: -------------------------------------------------------------------------------- 1 | context("all_attached") 2 | 3 | test_that("returns TRUE if all packages are attached, else returns FALSE", { 4 | expect_true(all_attached(c("base", "utils"))) 5 | expect_false(all_attached(c("base", "badpkg"))) 6 | }) 7 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # fgeo (development version) 2 | 3 | * Work in progress. 4 | 5 | # fgeo 1.1.4 6 | 7 | * Report downloads of fgeo packages from CRAN on fgeo home. 8 | * Maintenance release. 9 | 10 | # fgeo 1.1.3 11 | 12 | * First release on CRAN. 13 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/fgeo-package.R: -------------------------------------------------------------------------------- 1 | #' @keywords internal 2 | "_PACKAGE" 3 | 4 | # Suppress R CMD check note 5 | #' @importFrom fgeo.x example_path 6 | #' @importFrom fgeo.tool pick_dbh_min 7 | #' @importFrom fgeo.analyze abundance 8 | #' @importFrom fgeo.plot sp 9 | NULL 10 | 11 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^revdep$ 2 | ^cran-comments\.md$ 3 | ^tmp\.sh$ 4 | ^\.buildignore$ 5 | ^appveyor\.yml$ 6 | ^.*\.Rproj$ 7 | ^\.Rproj\.user$ 8 | ^README\.Rmd$ 9 | ^README-.*\.png$ 10 | ^\.travis\.yml$ 11 | ^docs$ 12 | ^_pkgdown\.yml$ 13 | ^LICENSE\.md$ 14 | ^pkgdown$ 15 | ^codecov\.yml$ 16 | ^\.github$ 17 | ^vignettes$ 18 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | aar 2 | Akre 3 | al 4 | Cmd 5 | csv 6 | CTFS 7 | Ctrl 8 | DOI 9 | eaar 10 | edu 11 | emphasise 12 | et 13 | fgeo's 14 | forestgeo 15 | ForestGEO 16 | funder 17 | github 18 | hsearch 19 | http 20 | https 21 | io 22 | krig 23 | LaManna 24 | lifecycle 25 | ly 26 | PIs 27 | Rprofile 28 | rstats 29 | RStudio 30 | si 31 | stemid 32 | Teixeira 33 | tidyverse 34 | tsv 35 | ViewFullTable 36 | ViewTaxonomy 37 | webrowser 38 | www 39 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(...) { 2 | if (all_attached(fgeo_to_attach())) { 3 | return() 4 | } 5 | 6 | crayon::num_colors(TRUE) 7 | fgeo_attach() 8 | 9 | x <- fgeo_conflicts() 10 | msg(fgeo_conflict_message(x), startup = TRUE) 11 | } 12 | 13 | all_attached <- function(packages) { 14 | needed <- packages[!is_attached(packages)] 15 | length(needed) == 0 16 | } 17 | 18 | is_attached <- function(x) { 19 | paste0("package:", x) %in% search() 20 | } 21 | -------------------------------------------------------------------------------- /fgeo.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 22 | -------------------------------------------------------------------------------- /.buildignore/jobs.R: -------------------------------------------------------------------------------- 1 | 2 | # Interactive 3 | # devtools::check_win_devel() 4 | # rhub::validate_email() 5 | ck_remote <- devtools::check(remote = TRUE) 6 | ck_cran <- rhub::check_for_cran() 7 | ck_macos <- rhub::check_on_macos() 8 | ck_fedora_cd <- rhub::check(platform = "fedora-clang-devel") 9 | ck_fedora_gd <- rhub::check(platform = "fedora-gcc-devel") 10 | ck_solaris <- rhub::check_on_solaris() 11 | 12 | # If has compiled code 13 | # rhub::check(platform = 'ubuntu-rchk') 14 | # rhub::check_with_sanitizers() 15 | -------------------------------------------------------------------------------- /tests/testthat/test-fgeo_help.R: -------------------------------------------------------------------------------- 1 | context("fgeo_help") 2 | 3 | test_that("outputs the expected class", { 4 | help_results <- fgeo_help("fgeo", package = "fgeo.tool") 5 | expect_is(help_results, "hsearch") 6 | }) 7 | 8 | test_that("oututs the same result", { 9 | expect_equal( 10 | help.search("abundance", package = "fgeo.analyze"), 11 | fgeo_help("abundance", package = "fgeo.analyze") 12 | ) 13 | expect_equal( 14 | fgeo_help("abundance", package = fgeo_packages()), 15 | fgeo_help("abundance") 16 | ) 17 | }) 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Please briefly describe your problem and what output you expect. If you have a question, please don't use this form. Instead, ask on , , or email Mauro Lepore at . 2 | 3 | Please include a minimal reproducible example (AKA a reprex). If you've never heard of a [reprex](http://reprex.tidyverse.org/) before, start by reading . 4 | 5 | --- 6 | 7 | Brief description of the problem 8 | 9 | ```r 10 | # insert reprex here 11 | ``` 12 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | 3 | * local: windows 10 x64 (R 3.6.0) 4 | * travis: ubuntu 14.04 (R 3.2, 3.3, 3.4, oldrel, release, devel) 5 | * win-builder (R devel and release) 6 | * rhub: x86_64-apple-darwin15.6.0 (R release) 7 | 8 | ## R CMD check results 9 | 10 | 0 errors | 0 warnings | 1 notes 11 | 12 | New maintainer: 13 | Mauro Lepore 14 | Old maintainer(s): 15 | Mauro Lepore 16 | 17 | * I have changed my email address in this and all other "fgeo" packages. 18 | 19 | ## Downstream dependencies 20 | 21 | There are currently no reverse dependencies for this package. 22 | -------------------------------------------------------------------------------- /man/fgeo_browse.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fgeo_browse.R 3 | \name{fgeo_browse} 4 | \alias{fgeo_browse} 5 | \alias{fgeo_browse_reference} 6 | \title{Open a web browser on fgeo's website.} 7 | \usage{ 8 | fgeo_browse() 9 | 10 | fgeo_browse_reference() 11 | } 12 | \description{ 13 | Load fgeo's URLs into an HTML browser. 14 | } 15 | \examples{ 16 | if (interactive()) { 17 | fgeo_browse() 18 | fgeo_browse_reference() 19 | } 20 | } 21 | \seealso{ 22 | Other functions to explore fgeo: \code{\link{fgeo_help}}, 23 | \code{\link{fgeo_packages}} 24 | } 25 | \concept{functions to explore fgeo} 26 | -------------------------------------------------------------------------------- /R/fgeo_browse.R: -------------------------------------------------------------------------------- 1 | fgeo_browse_url <- function(url) { 2 | force(url) 3 | function() { 4 | utils::browseURL(paste0("https://forestgeo.github.io/fgeo/", url)) 5 | invisible() 6 | } 7 | } 8 | 9 | #' Open a web browser on fgeo's website. 10 | #' 11 | #' Load fgeo's URLs into an HTML browser. 12 | #' 13 | #' @examples 14 | #' if (interactive()) { 15 | #' fgeo_browse() 16 | #' fgeo_browse_reference() 17 | #' } 18 | #' @family functions to explore fgeo 19 | #' @export 20 | fgeo_browse <- fgeo_browse_url("index.html") 21 | 22 | #' @rdname fgeo_browse 23 | #' @export 24 | fgeo_browse_reference <- fgeo_browse_url("articles/siteonly/reference.html") 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,fgeo_conflicts) 4 | export("%>%") 5 | export(fgeo_browse) 6 | export(fgeo_browse_reference) 7 | export(fgeo_help) 8 | export(fgeo_packages) 9 | importFrom(dplyr,arrange) 10 | importFrom(dplyr,filter) 11 | importFrom(dplyr,group_by) 12 | importFrom(dplyr,mutate) 13 | importFrom(dplyr,select) 14 | importFrom(dplyr,ungroup) 15 | importFrom(fgeo.analyze,abundance) 16 | importFrom(fgeo.plot,sp) 17 | importFrom(fgeo.tool,pick_dbh_min) 18 | importFrom(fgeo.x,example_path) 19 | importFrom(glue,glue) 20 | importFrom(magrittr,"%>%") 21 | importFrom(rlang,"%||%") 22 | importFrom(rlang,.data) 23 | importFrom(rlang,enquos) 24 | -------------------------------------------------------------------------------- /man/fgeo_packages.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fgeo_packages.R 3 | \name{fgeo_packages} 4 | \alias{fgeo_packages} 5 | \title{Names of the core fgeo packages.} 6 | \usage{ 7 | fgeo_packages(include_self = TRUE) 8 | } 9 | \arguments{ 10 | \item{include_self}{Logical. Should the output include fgeo?} 11 | } 12 | \value{ 13 | A string. 14 | } 15 | \description{ 16 | Names of the core fgeo packages. 17 | } 18 | \examples{ 19 | fgeo_packages() 20 | fgeo_packages(include_self = FALSE) 21 | } 22 | \seealso{ 23 | Other functions to explore fgeo: \code{\link{fgeo_browse}}, 24 | \code{\link{fgeo_help}} 25 | } 26 | \concept{functions to explore fgeo} 27 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | sudo: false 5 | cache: packages 6 | latex: false 7 | 8 | matrix: 9 | include: 10 | - r: devel 11 | - r: release 12 | after_success: Rscript -e 'covr::codecov()' 13 | before_deploy: 14 | - Rscript -e 'remotes::install_cran("pkgdown")' 15 | - Rscript -e 'remotes::install_cran("ggplot2")' 16 | - Rscript -e 'remotes::install_cran("cranlogs")' 17 | - Rscript -e 'remotes::install_cran("lubridate")' 18 | - Rscript -e 'remotes::install_github("maurolepore/pkgdoc")' 19 | deploy: 20 | provider: script 21 | script: Rscript -e 'pkgdown::deploy_site_github()' 22 | skip_cleanup: true 23 | - r: oldrel 24 | - r: 3.4 25 | - r: 3.3 26 | - r: 3.2 27 | 28 | -------------------------------------------------------------------------------- /.github/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | This document records developer-facing changes (users: see [NEWS](../NEWS.md)). 2 | 3 | # fgeo 1.1.2 ([GitHub](https://github.com/forestgeo/fgeo/releases) and [drat](https://forestgeo.github.io/drat/)) 4 | 5 | * [Builds on Travis CI](https://travis-ci.org/forestgeo/fgeo/builds/) are now tested on Windows, Mac, and Linux, and from R-devel to R 3.2 (see cran-comments.md). 6 | 7 | * The website now builds automatically and deploys on the `gh-branch`. 8 | 9 | * Automated builds of all __fgeo__ packages can now be tracked not only on [Travis CI](https://travis-ci.org/forestgeo/) but also on to the `#fgeo-builds` channel of [ForestGEO's slack workspace](https://forestgeo.slack.com/) ([request an invitation](https://github.com/forestgeo/forum/issues/new)). 10 | 11 | Thanks to the [reviewers](https://forestgeo.github.io/fgeo/authors.html)! 12 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | msg <- function(..., startup = FALSE) { 2 | if (startup) { 3 | if (!isTRUE(getOption("fgeo.quiet"))) { 4 | packageStartupMessage(text_col(...)) 5 | } 6 | } else { 7 | message(text_col(...)) 8 | } 9 | } 10 | 11 | text_col <- function(x) { 12 | # If RStudio not available, messages already printed in black 13 | if (!rstudioapi::isAvailable()) { 14 | return(x) 15 | } 16 | 17 | if (!rstudioapi::hasFun("getThemeInfo")) { 18 | return(x) 19 | } 20 | 21 | theme <- rstudioapi::getThemeInfo() 22 | 23 | if (isTRUE(theme$dark)) crayon::white(x) else crayon::black(x) 24 | } 25 | 26 | invert <- function(x) { 27 | if (length(x) == 0) return() 28 | stacked <- utils::stack(x) 29 | tapply(as.character(stacked$ind), stacked$values, list) 30 | } 31 | 32 | style_grey <- function(level, ...) { 33 | crayon::style( 34 | paste0(...), 35 | crayon::make_style(grDevices::grey(level), grey = TRUE) 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | # Adapt as necessary starting from here 17 | 18 | build_script: 19 | - travis-tool.sh install_deps 20 | 21 | test_script: 22 | - travis-tool.sh run_tests 23 | 24 | on_failure: 25 | - 7z a failure.zip *.Rcheck\* 26 | - appveyor PushArtifact failure.zip 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | -------------------------------------------------------------------------------- /R/fgeo_help.R: -------------------------------------------------------------------------------- 1 | #' Get help with fgeo. 2 | #' 3 | #' [fgeo_help()] finds all __fgeo__ help files. You can refine 4 | #' your search directly on the viewer panel of RStudio or via a string passed 5 | #' as the first argument to [fgeo_help()]. 6 | #' 7 | #' @param pattern A character string to be matched in the name, alias or title 8 | #' of a topic's documentation. Defaults to matching everything, which 9 | #' retrieves all the documentation of __fgeo__ packages. 10 | #' @param package A character string giving the name of one or more 11 | #' packages to limit the search, or `NULL` to search all fgeo packages. 12 | #' @inheritParams utils::help.search 13 | #' @param ... Other arguments passed to [utils::help.search()]. 14 | #' 15 | #' @seealso [utils::help.search()]. 16 | #' 17 | #' @return The results are returned in a list object of class "hsearch", which 18 | #' has a print method for nicely formatting the results of the query. 19 | #' 20 | #' @examples 21 | #' if (interactive()) { 22 | #' fgeo_help() 23 | #' } 24 | #' 25 | #' dplyr::as_tibble(fgeo_help()$matches) 26 | #' 27 | #' if (interactive()) { 28 | #' fgeo_help("stem", package = "fgeo.x") 29 | #' } 30 | #' @family functions to explore fgeo 31 | #' @export 32 | fgeo_help <- function(pattern = "", package = NULL, rebuild = TRUE, ...) { 33 | utils::help.search( 34 | pattern = pattern, 35 | package = package %||% fgeo_packages(), 36 | rebuild = rebuild, 37 | ... 38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /R/attach.R: -------------------------------------------------------------------------------- 1 | core_unloaded <- function() { 2 | search <- paste0("package:", fgeo_to_attach()) 3 | fgeo_to_attach()[!search %in% search()] 4 | } 5 | 6 | fgeo_attach <- function() { 7 | to_load <- core_unloaded() 8 | if (length(to_load) == 0) { 9 | return(invisible()) 10 | } 11 | 12 | msg( 13 | cli::rule( 14 | left = crayon::bold("Attaching packages"), 15 | right = paste0("fgeo ", package_version("fgeo")) 16 | ), 17 | startup = TRUE 18 | ) 19 | 20 | versions <- vapply(to_load, package_version, character(1)) 21 | packages <- paste0( 22 | crayon::green(cli::symbol$tick), " ", crayon::blue(format(to_load)), " ", 23 | crayon::col_align(versions, max(crayon::col_nchar(versions))) 24 | ) 25 | 26 | if (length(packages) %% 2 == 1) { 27 | packages <- append(packages, "") 28 | } 29 | 30 | col1 <- 1:floor(length(packages) / 2) 31 | info <- paste0(packages[col1], " ", packages[-col1]) 32 | 33 | msg(paste(info, collapse = "\n"), startup = TRUE) 34 | 35 | suppressPackageStartupMessages( 36 | lapply(to_load, library, character.only = TRUE, warn.conflicts = FALSE) 37 | ) 38 | 39 | invisible() 40 | } 41 | 42 | package_version <- function(x) { 43 | version <- as.character(unclass(utils::packageVersion(x))[[1]]) 44 | 45 | if (length(version) > 3) { 46 | version[4:length(version)] <- 47 | crayon::red(as.character(version[4:length(version)])) 48 | } 49 | paste0(version, collapse = ".") 50 | } 51 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http://contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /tests/testthat/test-fgeo_packages.R: -------------------------------------------------------------------------------- 1 | context("fgeo_packages") 2 | 3 | expect_sorted_equal <- function(object, expected, ...) { 4 | testthat::expect_equal(sort(object), sort(expected)) 5 | } 6 | 7 | test_that("is sensitive to `include_self`", { 8 | install_these <- c( 9 | "fgeo.x", 10 | "fgeo.tool", 11 | "fgeo.analyze", 12 | "fgeo.plot", 13 | "fgeo" 14 | ) 15 | expect_sorted_equal(fgeo_packages(), install_these) 16 | 17 | pkgs2 <- setdiff(install_these, "fgeo") 18 | expect_sorted_equal(fgeo_packages(FALSE), pkgs2) 19 | 20 | attach_these <- c( 21 | "fgeo.x", 22 | "fgeo.plot", 23 | "fgeo.analyze", 24 | "fgeo.tool" 25 | ) 26 | expect_sorted_equal(fgeo_to_attach(), attach_these) 27 | }) 28 | 29 | 30 | 31 | context("fgeo_dependencies") 32 | 33 | test_that("is sensitive to `matches`", { 34 | expect_true(any(grepl("^cli$", fgeo_dependencies()))) 35 | expect_false(any(grepl("^cli$", fgeo_dependencies(matches = "fgeo")))) 36 | expect_true(any(grepl("^fgeo$", fgeo_dependencies(matches = "fgeo")))) 37 | expect_true(any(grepl("^fgeo.x$", fgeo_dependencies(matches = "fgeo")))) 38 | }) 39 | 40 | test_that("is sensitive to `include_fgeo`", { 41 | expect_false( 42 | any(grepl("^fgeo$", fgeo_dependencies("fgeo", include_self = FALSE))) 43 | ) 44 | expect_true( 45 | any(grepl("^fgeo.x$", fgeo_dependencies("fgeo", include_self = FALSE))) 46 | ) 47 | }) 48 | 49 | test_that("warns nonsenseical argument combination", { 50 | expect_message( 51 | fgeo_dependencies("fgeo", include_self = TRUE, section = "Suggests"), 52 | "Ignoring" 53 | ) 54 | }) 55 | -------------------------------------------------------------------------------- /man/fgeo_help.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fgeo_help.R 3 | \name{fgeo_help} 4 | \alias{fgeo_help} 5 | \title{Get help with fgeo.} 6 | \usage{ 7 | fgeo_help(pattern = "", package = NULL, rebuild = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{pattern}{A character string to be matched in the name, alias or title 11 | of a topic's documentation. Defaults to matching everything, which 12 | retrieves all the documentation of \strong{fgeo} packages.} 13 | 14 | \item{package}{A character string giving the name of one or more 15 | packages to limit the search, or \code{NULL} to search all fgeo packages.} 16 | 17 | \item{rebuild}{a logical indicating whether the help database should 18 | be rebuilt. This will be done automatically if \code{lib.loc} or 19 | the search path is changed, or if \code{package} is used and a value 20 | is not found.} 21 | 22 | \item{...}{Other arguments passed to \code{\link[utils:help.search]{utils::help.search()}}.} 23 | } 24 | \value{ 25 | The results are returned in a list object of class "hsearch", which 26 | has a print method for nicely formatting the results of the query. 27 | } 28 | \description{ 29 | \code{\link[=fgeo_help]{fgeo_help()}} finds all \strong{fgeo} help files. You can refine 30 | your search directly on the viewer panel of RStudio or via a string passed 31 | as the first argument to \code{\link[=fgeo_help]{fgeo_help()}}. 32 | } 33 | \examples{ 34 | if (interactive()) { 35 | fgeo_help() 36 | } 37 | 38 | dplyr::as_tibble(fgeo_help()$matches) 39 | 40 | if (interactive()) { 41 | fgeo_help("stem", package = "fgeo.x") 42 | } 43 | } 44 | \seealso{ 45 | \code{\link[utils:help.search]{utils::help.search()}}. 46 | 47 | Other functions to explore fgeo: \code{\link{fgeo_browse}}, 48 | \code{\link{fgeo_packages}} 49 | } 50 | \concept{functions to explore fgeo} 51 | -------------------------------------------------------------------------------- /R/fgeo_packages.R: -------------------------------------------------------------------------------- 1 | #' Names of the core fgeo packages. 2 | #' 3 | #' @param include_self Logical. Should the output include fgeo? 4 | #' @return A string. 5 | #' @export 6 | #' @family functions to explore fgeo 7 | #' @examples 8 | #' fgeo_packages() 9 | #' fgeo_packages(include_self = FALSE) 10 | fgeo_packages <- function(include_self = TRUE) { 11 | fgeo <- fgeo_dependencies( 12 | matches = "fgeo", include_self = TRUE, section = "Imports" 13 | ) 14 | 15 | if (include_self) { 16 | return(fgeo) 17 | } 18 | 19 | grep("^fgeo$", fgeo, invert = TRUE, value = TRUE) 20 | } 21 | 22 | fgeo_to_attach <- function() { 23 | fgeo_packages(include_self = FALSE) 24 | } 25 | 26 | 27 | 28 | #' List package dependencies (imports and suggests) of __fgeo__. 29 | #' 30 | #' @param matches String to `grep()` the output. 31 | #' @param include_self Include fgeo in the list? 32 | #' @param section Either "Imports" or "Suggests". 33 | #' @return A string. 34 | #' 35 | #' @family functions for developers 36 | #' @noRd 37 | fgeo_dependencies <- function(matches = NULL, 38 | include_self = TRUE, 39 | section = c("Imports", "Suggests")) { 40 | section <- section[[1]] 41 | raw <- utils::packageDescription("fgeo")[[section]] 42 | pulled <- strsplit(raw, ",")[[1]] 43 | parsed <- gsub("^\\s+|\\s+$", "", pulled) 44 | names <- vapply(strsplit(parsed, " +"), "[[", 1, FUN.VALUE = character(1)) 45 | 46 | if (section == "Suggests") { 47 | if (include_self) { 48 | message( 49 | "Ignoring argument `ignore_self` (it makes no sense for 'Suggests')." 50 | ) 51 | } 52 | return(names) 53 | } 54 | 55 | if (include_self) { 56 | names <- c(names, "fgeo") 57 | } 58 | 59 | if (!is.null(matches)) { 60 | names <- grep(matches, names, value = TRUE) 61 | } 62 | 63 | names 64 | } 65 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Getting help with fgeo 2 | 3 | Thanks for using fgeo. Before filing an issue, there are a few places 4 | to explore and pieces to put together to make the process as smooth as possible. 5 | 6 | Start by making a minimal **repr**oducible **ex**ample using the 7 | [reprex](http://reprex.tidyverse.org/) package. If you haven't heard of or used 8 | reprex before, you're in for a treat! Seriously, reprex will make all of your 9 | R-question-asking endeavors easier (which is a pretty insane ROI for the five to 10 | ten minutes it'll take you to learn what it's all about). For additional reprex 11 | pointers, check out the [Get help!](https://www.tidyverse.org/help/) section of 12 | the tidyverse site. 13 | 14 | Armed with your reprex, the next step is to figure out [where to ask](https://www.tidyverse.org/help/#where-to-ask). 15 | 16 | * If it's a question: start with [community.rstudio.com](https://community.rstudio.com/), 17 | and/or StackOverflow. There are more people there to answer questions. 18 | * If it's a bug: you're in the right place, file an issue. 19 | * If you're not sure: let the community help you figure it out! If your 20 | problem _is_ a bug or a feature request, you can easily return here and 21 | report it. 22 | 23 | Before opening a new issue, be sure to search _issues_ and _pull requests_ in the relavant package ([here is the list of all __fgeo__ packages](https://github.com/forestgeo/fgeo/issues)) to make sure the bug 24 | hasn't been reported and/or already fixed in the development version. By 25 | default, the search will be pre-populated with `is:issue is:open`. You can 26 | [edit the qualifiers](https://help.github.com/articles/searching-issues-and-pull-requests/) (e.g. `is:pr`, `is:closed`) as needed. For example, you'd simply 27 | remove `is:open` to search _all_ issues in the repo, open or closed. 28 | 29 | 30 | If you _are_ in the right place, and need to file an issue, please review the 31 | ["File issues"](https://www.tidyverse.org/contribute/#issues) paragraph from 32 | the tidyverse contributing guidelines. 33 | 34 | Thanks for your help! 35 | -------------------------------------------------------------------------------- /R/conflicts.R: -------------------------------------------------------------------------------- 1 | #' Conflicts between the __fgeo__ and other packages. 2 | #' 3 | #' This function lists all the conflicts between packages in fgeo 4 | #' and other packages that you have loaded. 5 | #' @noRd 6 | fgeo_conflicts <- function() { 7 | envs <- purrr::set_names(search()) 8 | 9 | objs <- invert(lapply(envs, function(env) ls(pos = env))) 10 | 11 | conflicts <- purrr::keep(objs, ~ length(.x) > 1) 12 | 13 | fgeo_imports <- fgeo_dependencies(section = "Imports", include_self = TRUE) 14 | fgeo_names <- paste0("package:", fgeo_imports) 15 | conflicts <- purrr::keep(conflicts, ~ any(.x %in% fgeo_names)) 16 | 17 | conflict_funs <- purrr::imap(conflicts, confirm_conflict) 18 | conflict_funs <- purrr::compact(conflict_funs) 19 | 20 | structure(conflict_funs, class = "fgeo_conflicts") 21 | } 22 | 23 | fgeo_conflict_message <- function(x) { 24 | if (length(x) == 0) return("") 25 | 26 | header <- cli::rule( 27 | left = crayon::bold("Conflicts"), 28 | right = "fgeo_conflicts()" 29 | ) 30 | 31 | pkgs <- purrr::map(x, ~ gsub("^package:", "", .)) 32 | others <- purrr::map(pkgs, `[`, -1) 33 | other_calls <- purrr::map2_chr( 34 | others, names(others), 35 | ~ paste0(crayon::blue(.x), "::", .y, "()", collapse = ", ") 36 | ) 37 | 38 | winner <- purrr::map_chr(pkgs, 1) 39 | funs <- format(paste0(crayon::blue(winner), "::", crayon::green(paste0(names(x), "()")))) 40 | bullets <- paste0( 41 | crayon::red(cli::symbol$cross), " ", funs, 42 | " masks ", other_calls, 43 | collapse = "\n" 44 | ) 45 | 46 | paste0(header, "\n", bullets) 47 | } 48 | 49 | #' @export 50 | print.fgeo_conflicts <- function(x, ..., startup = FALSE) { 51 | cli::cat_line(fgeo_conflict_message(x)) 52 | } 53 | 54 | confirm_conflict <- function(packages, name) { 55 | # Only look at functions 56 | objs <- purrr::keep( 57 | purrr::map(packages, ~ get(name, pos = .)), 58 | is.function 59 | ) 60 | 61 | if (length(objs) <= 1) { 62 | return() 63 | } 64 | 65 | # Remove identical functions 66 | objs <- objs[!duplicated(objs)] 67 | packages <- packages[!duplicated(packages)] 68 | if (length(objs) == 1) { 69 | return() 70 | } 71 | 72 | packages 73 | } 74 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | # fgeo 2 | 3 |
4 | 5 | * Version: 6 | * Source code: ??? 7 | * URL: http://forestgeo.github.io/fgeo, https://github.com/forestgeo/fgeo 8 | * BugReports: https://github.com/forestgeo/fgeo/issues 9 | * Number of recursive dependencies: 0 10 | 11 | Run `revdep_details(,"")` for more info 12 | 13 |
14 | 15 | ## Error before installation 16 | 17 | ### Devel 18 | 19 | ``` 20 | 21 | 22 | 23 | 24 | 25 | 26 | ``` 27 | ### CRAN 28 | 29 | ``` 30 | 31 | 32 | 33 | 34 | 35 | 36 | ``` 37 | # fgeo.analyze 38 | 39 |
40 | 41 | * Version: 42 | * Source code: ??? 43 | * URL: http://forestgeo.github.io/fgeo, https://github.com/forestgeo/fgeo 44 | * BugReports: https://github.com/forestgeo/fgeo/issues 45 | * Number of recursive dependencies: 0 46 | 47 | Run `revdep_details(,"")` for more info 48 | 49 |
50 | 51 | ## Error before installation 52 | 53 | ### Devel 54 | 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | 62 | ``` 63 | ### CRAN 64 | 65 | ``` 66 | 67 | 68 | 69 | 70 | 71 | 72 | ``` 73 | # fgeo.plot 74 | 75 |
76 | 77 | * Version: 78 | * Source code: ??? 79 | * URL: http://forestgeo.github.io/fgeo, https://github.com/forestgeo/fgeo 80 | * BugReports: https://github.com/forestgeo/fgeo/issues 81 | * Number of recursive dependencies: 0 82 | 83 | Run `revdep_details(,"")` for more info 84 | 85 |
86 | 87 | ## Error before installation 88 | 89 | ### Devel 90 | 91 | ``` 92 | 93 | 94 | 95 | 96 | 97 | 98 | ``` 99 | ### CRAN 100 | 101 | ``` 102 | 103 | 104 | 105 | 106 | 107 | 108 | ``` 109 | # fgeo.tool 110 | 111 |
112 | 113 | * Version: 114 | * Source code: ??? 115 | * URL: http://forestgeo.github.io/fgeo, https://github.com/forestgeo/fgeo 116 | * BugReports: https://github.com/forestgeo/fgeo/issues 117 | * Number of recursive dependencies: 0 118 | 119 | Run `revdep_details(,"")` for more info 120 | 121 |
122 | 123 | ## Error before installation 124 | 125 | ### Devel 126 | 127 | ``` 128 | 129 | 130 | 131 | 132 | 133 | 134 | ``` 135 | ### CRAN 136 | 137 | ``` 138 | 139 | 140 | 141 | 142 | 143 | 144 | ``` 145 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to fgeo 2 | 3 | This outlines how to propose a change to __fgeo__. For more detailed 4 | info about contributing to this, and other __fgeo__ packages (), please see the 5 | [**development contributing guide of the tidyverse**](https://rstd.io/tidy-contrib) (wherever you read __tidyverse__ think __fgeo__). 6 | 7 | ### Fixing typos 8 | 9 | Small typos or grammatical errors in documentation may be edited directly using 10 | the GitHub web interface, so long as the changes are made in the _source_ file. 11 | 12 | * YES: you edit a roxygen comment in a `.R` file below `R/`. 13 | * NO: you edit an `.Rd` file below `man/`. 14 | 15 | ### Prerequisites 16 | 17 | Before you make a substantial pull request, you should always file an issue and 18 | make sure someone from the team agrees that it's a problem. If you've found a 19 | bug, create an associated issue and illustrate the bug with a minimal 20 | [reprex](https://www.tidyverse.org/help/#reprex). 21 | 22 | ### Pull request process 23 | 24 | * We recommend that you create a Git branch for each pull request (PR). 25 | * Look at the Travis build status before and after making changes. 26 | The `README` should contain badges for any continuous integration services used 27 | by the package. 28 | * New code should follow the tidyverse [style guide](http://style.tidyverse.org). 29 | You can use the [styler](https://CRAN.R-project.org/package=styler) package to 30 | apply these styles, but please don't restyle code that has nothing to do with 31 | your PR. 32 | * We use [roxygen2](https://cran.r-project.org/package=roxygen2), with 33 | [Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/markdown.html), 34 | for documentation. 35 | * We use [testthat](https://cran.r-project.org/package=testthat). Contributions 36 | with test cases included are easier to accept. 37 | * For user-facing changes, add a bullet to the top of `NEWS.md` below the current 38 | development version header describing the changes made followed by your GitHub 39 | username, and links to relevant issue(s)/PR(s). 40 | 41 | ### Code of Conduct 42 | 43 | Please note that this project is released with a [Contributor Code of 44 | Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to 45 | abide by its terms. 46 | 47 | ### See tidyverse [development contributing guide](https://rstd.io/tidy-contrib) for further details (wherever you read __tidyverse__ think __fgeo__). 48 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | navbar: 2 | type: default 3 | left: 4 | - text: "Reference" 5 | href: articles/siteonly/reference.html 6 | - text: "Tutorials" 7 | menu: 8 | - text: "Visualization basics" 9 | href: https://fgeocomm.shinyapps.io/basics-vis/ 10 | - text: "Programming basics" 11 | href: https://fgeocomm.shinyapps.io/basics-programming/ 12 | - text: "Tibbles" 13 | href: https://fgeocomm.shinyapps.io/transform-tibbles/ 14 | - text: "Isolating data with dplyr" 15 | href: https://fgeocomm.shinyapps.io/transform-isolating/ 16 | - text: "Exploratory data analysis" 17 | href: https://bookdown.org/fgeocomm/eda/ 18 | 19 | right: 20 | - text: "Community" 21 | menu: 22 | - text: "Release candidate 1.2.0" 23 | href: articles/siteonly/fgeo-1-2-0-release-candidate.html 24 | - text: "Q&A" 25 | href: articles/siteonly/questions-and-answers.html 26 | - text: "Try fgeo in rstudio.cloud" 27 | href: https://rstudio.cloud/project/43852 28 | - text: "Resources" 29 | href: https://github.com/forestgeo/learn/issues 30 | - text: "Discuss" 31 | href: https://github.com/forestgeo/forum/issues 32 | - text: "Blog" 33 | href: https://fgeo.netlify.com/ 34 | - icon: fa-gavel 35 | href: https://github.com/maurolepore 36 | - icon: fa-github 37 | href: https://github.com/forestgeo/fgeo 38 | 39 | url: https://forestgeo.github.io/fgeo/ 40 | 41 | template: 42 | params: 43 | bootswatch: united 44 | 45 | toc: 46 | depth: 3 47 | 48 | authors: 49 | Mauro Lepore: 50 | href: https://forestgeo.si.edu/mauro-lepore 51 | Gabriel Arellano: 52 | href: https://forestgeo.si.edu/arellano-gabriel 53 | Stuart Davies: 54 | href: https://forestgeo.si.edu/stuart-j-davies 55 | Erika Gonzalez-Akre: 56 | href: https://sites.google.com/site/forestecoclimlab/people 57 | Valentine Herrmann: 58 | href: https://valentineherr.github.io/ 59 | Aaron Hogan: 60 | href: https://www.jamesaaronhogan.com/ 61 | David Kenfack: 62 | href: https://forestgeo.si.edu/david-kenfack 63 | Bier Kraichak: 64 | href: https://kraichak.weebly.com/ 65 | Lauren Krizel: 66 | href: https://forestgeo.si.edu/lauren-krizel 67 | Suzanne Lao: 68 | href: https://forestgeo.si.edu/suzanne-lao 69 | Sean McMahon: 70 | href: https://forestgeo.si.edu/sean-mcmahon 71 | Kristina Teixeira: 72 | href: https://forestgeo.si.edu/kristina-j-anderson-teixeira 73 | Sabrina Russo: 74 | href: http://russolab.unl.edu 75 | CTFS-ForestGEO: 76 | href: http://www.forestgeo.si.edu/ 77 | -------------------------------------------------------------------------------- /man/fgeo-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/fgeo-package.R 3 | \docType{package} 4 | \name{fgeo-package} 5 | \alias{fgeo} 6 | \alias{fgeo-package} 7 | \title{fgeo: Analyze Forest Diversity and Dynamics} 8 | \description{ 9 | To help you access, transform, analyze, and 10 | visualize ForestGEO data, we developed a collection of R packages 11 | (). This package, in particular, 12 | helps you to install and load the entire package-collection with a 13 | single R command, and provides convenient ways to find relevant 14 | documentation. Most commonly, you should not worry about the 15 | individual packages that make up the package-collection as you can 16 | access all features via this package. To learn more about ForestGEO 17 | visit . 18 | } 19 | \seealso{ 20 | Useful links: 21 | \itemize{ 22 | \item \url{http://forestgeo.github.io/fgeo} 23 | \item \url{https://github.com/forestgeo/fgeo} 24 | \item Report bugs at \url{https://github.com/forestgeo/fgeo/issues} 25 | } 26 | 27 | } 28 | \author{ 29 | \strong{Maintainer}: Mauro Lepore \email{maurolepore@gmail.com} (0000-0002-1986-7988) [contractor] 30 | 31 | Authors: 32 | \itemize{ 33 | \item Gabriel Arellano \email{gabriel.arellano.torres@gmail.com} [reviewer] 34 | \item Richard Condit \email{richardcondit@gmail.com} 35 | \item Stuart Davies \email{daviess@si.edu} [reviewer] 36 | \item Matteo Detto \email{teoparaglider@gmail.com} 37 | \item Erika Gonzalez-Akre \email{GonzalezEB@si.edu} (0000-0001-8305-6672) [reviewer] 38 | \item Pamela Hall \email{phall@alum.mit.edu} 39 | \item Kyle Harms \email{ kharms@lsu.edu} 40 | \item Valentine Herrmann \email{HerrmannV@si.edu} (0000-0002-4519-481X) [reviewer] 41 | \item David Kenfack \email{KenfackD@si.edu } [reviewer] 42 | \item Suzanne Lao \email{laoz@si.edu} [reviewer] 43 | \item Sean McMahon \email{mcmahons@si.edu} [reviewer] 44 | \item Sabrina Russo \email{srusso2@unl.edu} [reviewer] 45 | \item Kristina Anderson-Teixeira \email{TeixeiraK@si.edu} [reviewer] 46 | \item Graham Zemunik \email{grah.zem@gmail.com} [reviewer] 47 | \item Daniel Zuleta \email{dfzuleta@gmail.com} [reviewer] 48 | } 49 | 50 | Other contributors: 51 | \itemize{ 52 | \item Aaron Hogan \email{jamesaaronhogan@gmail.com} (0000-0001-9806-3074) [reviewer] 53 | \item Bier Kraichak \email{ekraichak@gmail.com} [reviewer] 54 | \item Lauren Krizel \email{KrizelL@si.edu} [reviewer] 55 | \item Haley Overstreet \email{OverstreetH@si.edu} [reviewer] 56 | \item Cara Scalpone \email{ScalponeC@si.edu} (0000-0001-8448-2147) [reviewer] 57 | \item CTFS-ForestGEO \email{ForestGEO@si.edu} [copyright holder, funder] 58 | } 59 | 60 | } 61 | \keyword{internal} 62 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:----------------------------| 5 | |version |R version 3.6.0 (2019-04-26) | 6 | |os |Ubuntu 18.04.2 LTS | 7 | |system |x86_64, linux-gnu | 8 | |ui |RStudio | 9 | |language |(EN) | 10 | |collate |C.UTF-8 | 11 | |ctype |C.UTF-8 | 12 | |tz |America/Costa_Rica | 13 | |date |2019-06-18 | 14 | 15 | # Dependencies 16 | 17 | |package |old |new |Δ | 18 | |:------------|:--------|:----------|:--| 19 | |fgeo |1.1.3 |1.1.3.9000 |* | 20 | |assertthat |0.2.1 |0.2.1 | | 21 | |backports |1.1.4 |1.1.4 | | 22 | |BH |1.69.0-1 |1.69.0-1 | | 23 | |cli |1.1.0 |1.1.0 | | 24 | |clipr |0.6.0 |0.6.0 | | 25 | |colorspace |1.4-1 |1.4-1 | | 26 | |crayon |1.3.4 |1.3.4 | | 27 | |digest |0.6.19 |0.6.19 | | 28 | |dplyr |0.8.1 |0.8.1 | | 29 | |fansi |0.4.0 |0.4.0 | | 30 | |fgeo.analyze |1.1.10 |1.1.10 | | 31 | |fgeo.plot |1.1.8 |1.1.8 | | 32 | |fgeo.tool |1.2.5 |1.2.5 | | 33 | |fgeo.x |1.1.4 |1.1.4 | | 34 | |ggplot2 |3.2.0 |3.2.0 | | 35 | |ggrepel |0.8.1 |0.8.1 | | 36 | |glue |1.3.1 |1.3.1 | | 37 | |gtable |0.3.0 |0.3.0 | | 38 | |hms |0.4.2 |0.4.2 | | 39 | |labeling |0.3 |0.3 | | 40 | |lazyeval |0.2.2 |0.2.2 | | 41 | |lubridate |1.7.4 |1.7.4 | | 42 | |memoise |1.1.0 |1.1.0 | | 43 | |munsell |0.5.0 |0.5.0 | | 44 | |pillar |1.4.1 |1.4.1 | | 45 | |plogr |0.2.0 |0.2.0 | | 46 | |plyr |1.8.4 |1.8.4 | | 47 | |purrr |0.3.2 |0.3.2 | | 48 | |RColorBrewer |1.1-2 |1.1-2 | | 49 | |Rcpp |1.0.1 |1.0.1 | | 50 | |readr |1.3.1 |1.3.1 | | 51 | |reshape2 |1.4.3 |1.4.3 | | 52 | |rlang |0.3.4 |0.3.4 | | 53 | |rstudioapi |0.10 |0.10 | | 54 | |scales |1.0.0 |1.0.0 | | 55 | |stringi |1.4.3 |1.4.3 | | 56 | |stringr |1.4.0 |1.4.0 | | 57 | |tibble |2.1.3 |2.1.3 | | 58 | |tidyr |0.8.3 |0.8.3 | | 59 | |tidyselect |0.2.5 |0.2.5 | | 60 | |utf8 |1.1.4 |1.1.4 | | 61 | |vctrs |0.1.0 |0.1.0 | | 62 | |viridisLite |0.3.0 |0.3.0 | | 63 | |withr |2.1.2 |2.1.2 | | 64 | |zeallot |0.1.0 |0.1.0 | | 65 | 66 | # Revdeps 67 | 68 | ## Failed to check (4) 69 | 70 | |package |version |error |warning |note | 71 | |:------------|:-------|:-----|:-------|:----| 72 | |fgeo |? | | | | 73 | |fgeo.analyze |? | | | | 74 | |fgeo.plot |? | | | | 75 | |fgeo.tool |? | | | | 76 | 77 | -------------------------------------------------------------------------------- /vignettes/siteonly/reference.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Reference" 3 | output: html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Quick Search} 6 | %\VignetteEncoding{UTF-8} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | editor_options: 9 | chunk_output_type: console 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | echo = FALSE, 15 | message = FALSE, 16 | warning = FALSE, 17 | collapse = TRUE, 18 | comment = "#>" 19 | ) 20 | ``` 21 | 22 | ```{r} 23 | library(dplyr) 24 | library(fgeo) 25 | library(pkgdoc) 26 | ``` 27 | 28 | ```{r, warning=FALSE} 29 | 30 | url_fgeo <- "https://forestgeo.github.io/" 31 | 32 | fgeo_reference_concept <- function(x) { 33 | reference_concept(x, url = url_fgeo, packages = fgeo:::fgeo_packages()) %>% 34 | custom_table() 35 | } 36 | 37 | fgeo_reference_package <- function(x) { 38 | reference_package(x, url = url_fgeo, packages = fgeo:::fgeo_packages()) %>% 39 | custom_table() 40 | } 41 | 42 | custom_table <- function(x) { 43 | x %>% 44 | select(-package, -concept) %>% 45 | unique() %>% 46 | knitr::kable( 47 | x, 48 | format = "html", 49 | col.names = NULL, 50 | escape = FALSE 51 | ) %>% 52 | kableExtra::column_spec(1, bold = TRUE) %>% 53 | kableExtra::column_spec(2, width = "20em") 54 | } 55 | ``` 56 | 57 | Search globally in the search box below, or navigate the index clicking the menu on the right. 58 | 59 | ### Global search 60 | 61 | ```{r, warning=FALSE} 62 | fgeo:::fgeo_packages() %>% 63 | purrr::map_dfr(reference_package, url = url_fgeo) %>% 64 | select(-package, -concept) %>% 65 | unique() %>% 66 | purrr::set_names(c("", "object", "description")) %>% 67 | DT::datatable( 68 | escape = FALSE, 69 | rownames = NULL, 70 | options = list( 71 | # f: filter, t: table, i: information 72 | dom = "fti", 73 | search = list(search = "topography") 74 | ) 75 | ) 76 | ``` 77 | 78 | ### Explore fgeo 79 | 80 | ```{r} 81 | fgeo_reference_concept("functions to explore fgeo") 82 | ``` 83 | 84 | ### Plot 85 | 86 | ```{r} 87 | fgeo_reference_concept("plot functions") 88 | ``` 89 | 90 | ### Abundance 91 | 92 | ```{r} 93 | fgeo_reference_concept("functions for abundance and basal area") 94 | ``` 95 | 96 | ### Demography 97 | 98 | ```{r} 99 | fgeo_reference_concept("demography functions") 100 | ``` 101 | 102 | ### Habitat 103 | 104 | ```{r} 105 | fgeo_reference_concept("habitat functions") 106 | ``` 107 | 108 | ### Import and manipulate ForestGEO data 109 | 110 | #### Import ForestGEO data 111 | 112 | ```{r} 113 | fgeo_reference_concept("functions to import ForestGEO data") 114 | ``` 115 | 116 | #### Edit data in place 117 | 118 | ```{r} 119 | fgeo_reference_concept(c( 120 | "functions to edit ForestGEO data in place", 121 | "general functions to edit data in place" 122 | )) 123 | ``` 124 | 125 | #### Pick/drop rows with matching conditions 126 | 127 | ```{r} 128 | fgeo_reference_concept(c( 129 | "general functions to pick or drop rows of a dataframe", 130 | "functions to pick or drop rows of a ForestGEO dataframe" 131 | )) 132 | ``` 133 | 134 | #### Add new columns to a dataframe 135 | 136 | ```{r} 137 | fgeo_reference_concept("functions to add columns to dataframes") 138 | ``` 139 | 140 | ### Datasets 141 | 142 | ```{r} 143 | fgeo_reference_concept("datasets") 144 | ``` 145 | -------------------------------------------------------------------------------- /vignettes/siteonly/fgeo-1-2-0-release-candidate.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "fgeo 1.2.0 release candidate" 3 | output: rmarkdown::html_vignette 4 | editor_options: 5 | chunk_output_type: console 6 | --- 7 | 8 | ```{r setup, include = FALSE} 9 | knitr::opts_chunk$set( 10 | collapse = TRUE, 11 | eval = TRUE, 12 | comment = "#>", 13 | fig.show = "hold", 14 | fig.align = "center", 15 | out.width = "70%", 16 | fig.width = 9.5, 17 | fig.asp = 0.7 18 | ) 19 | 20 | options(fgeo.quiet = TRUE) 21 | ``` 22 | 23 | [__fgeo__](https://forestgeo.github.io/fgeo/index.html) is a collection of R packages to analyze forest diversity and dynamics. We plan to announce it widely in early 2019. Before that, we would love you to [give us some feedback, and report issues](https://github.com/forestgeo/fgeo/issues). 24 | 25 | This post highlights the main features. For more details please see the [Example](https://forestgeo.github.io/fgeo/index.html#example) and [Reference](https://forestgeo.github.io/fgeo/articles/siteonly/reference.html) sections. 26 | 27 | ### Setup 28 | 29 | To install __fgeo__ see [Installation](https://forestgeo.github.io/fgeo/#installation). To use __fgeo__ run `library(fgeo)` in R. 30 | 31 | ```{r} 32 | library(fgeo) 33 | ``` 34 | 35 | All __fgeo__ packages are now attached. 36 | 37 | ```{r} 38 | search() 39 | ``` 40 | 41 | ### Explore fgeo 42 | 43 | Use [`fgeo_help()`](https://forestgeo.github.io/fgeo/reference/fgeo_help) to search documentation. It is similar to `utils::help.search()` but specific for __fgeo__. 44 | 45 | ### Access and manipulate data 46 | 47 | __fgeo__ comes with small datasets for examples. When you use __fgeo__ you can also use many datasets directly. 48 | 49 | ```{r} 50 | tree5 51 | ``` 52 | 53 | Other datasets are stored in R's library. You can access them with [`example_path()`](https://forestgeo.github.io/fgeo.x/reference/example_path). 54 | 55 | ```{r} 56 | example_path("rdata") 57 | 58 | dir(example_path("rdata")) 59 | ``` 60 | 61 | Larger datasets live online. You can download them with [`download_data()`](https://forestgeo.github.io/fgeo.x/reference/download_data). 62 | 63 | ```{r} 64 | download_data("luquillo_tree5_random") 65 | ``` 66 | 67 | Use [`read_vft()`](https://forestgeo.github.io/fgeo.tool/reference/read_vft) to read your own ViewFullTable. Compared to `utils::read.csv()` it is easier to use and safer. 68 | 69 | ```{r} 70 | (viewfulltable_file <- example_path("view/vft_4quad.csv")) 71 | 72 | read_vft(viewfulltable_file) 73 | ``` 74 | 75 | ### Plot 76 | 77 | ```{r} 78 | # Using only two species to keep the example small 79 | two_species <- c("PREMON", "CASARB") 80 | 81 | # The pipe operator (`%>%`) can make your code easier to read 82 | census <- download_data("luquillo_stem6_random") %>% 83 | filter(sp %in% two_species) 84 | ``` 85 | 86 | Use `autoplot()` to plot different classes of ForestGEO data. For example: 87 | 88 | * [`autoplot()` species distribution](https://forestgeo.github.io/fgeo.plot/reference/autoplot.sp_elev) 89 | 90 | ```{r} 91 | class(sp(census)) 92 | 93 | autoplot(sp(census)) 94 | ``` 95 | 96 | * [`autoplot()` habitats](https://forestgeo.github.io/fgeo.plot/reference/autoplot.fgeo_habitat) 97 | 98 | ```{r} 99 | # Using `data()` just for clarity 100 | data("habitat") 101 | 102 | class(habitat) 103 | 104 | autoplot(habitat) 105 | ``` 106 | 107 | ### Analyze 108 | 109 | The available analyses include [abundance](https://forestgeo.github.io/fgeo.analyze/reference/abundance), [mortality](https://forestgeo.github.io/fgeo.analyze/reference/recruitment_ctfs), and [species-habitat association](https://forestgeo.github.io/fgeo.analyze/reference/tt_test). 110 | 111 | ```{r} 112 | census %>% 113 | pick_main_stem() %>% 114 | group_by(sp) %>% 115 | abundance() 116 | ``` 117 | 118 | ```{r} 119 | data("tree5") 120 | data("tree6") 121 | 122 | as_tibble( 123 | mortality_ctfs(tree5, tree6) 124 | ) 125 | ``` 126 | 127 | ```{r} 128 | tree <- download_data("luquillo_tree5_random") 129 | data("habitat") 130 | 131 | summary( 132 | tt_test(tree, habitat) 133 | ) 134 | ``` 135 | 136 | [Get started with __fgeo__](https://forestgeo.github.io/fgeo/) 137 | -------------------------------------------------------------------------------- /vignettes/siteonly/questions-and-answers.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Questions and Answers" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Questions and Answers} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | warning = FALSE, 14 | comment = "#>" 15 | ) 16 | ``` 17 | 18 | ## How to setup .Rprofile for easiest installation of __fgeo__? 19 | 20 | 1. Open .Rprofile (e.g. with [`usethis::edit_r_profile()`](https://usethis.r-lib.org/reference/edit.html)) and add this code: 21 | 22 | ```R 23 | .First <- function() { 24 | options( 25 | repos = c( 26 | CRAN = "https://cran.rstudio.com/", 27 | forestgeo = "https://forestgeo.github.io/drat" 28 | ) 29 | ) 30 | } 31 | ``` 32 | 33 | 2. Save .Rprofile, close it, and restart R. 34 | 35 | In every R session you can now install __fgeo__ with `install.packages("fgeo")`. 36 | 37 | ## How to update __fgeo__? 38 | 39 | ```R 40 | update.packages(repos = "https://forestgeo.github.io/drat/") 41 | ``` 42 | 43 | ## How to remove __fgeo__? 44 | 45 | ```R 46 | remove.packages(fgeo::fgeo_packages()) 47 | ``` 48 | 49 | ## How to avoid or fix common installation problems? 50 | 51 | #### Update R, RStudio, and R packages 52 | 53 | * [How?](https://fgeo.netlify.com/2018/02/08/2018-02-08-update-r-rstudio-and-r-packages/) 54 | * [Why?](https://fgeo.netlify.com/2018/03/06/2018-03-06-should-i-update-all-my-r-packages-frequently-yes-no-why/) 55 | 56 | #### Instruct RStudio not to preserve your workspace between sessions 57 | 58 | * [Why?](https://r4ds.had.co.nz/workflow-projects.html#what-is-real) 59 | 60 | In RStudio go to _Tools > Global Options..._ 61 | 62 | 63 | 64 | #### Use RStudio projects (or the [__here__](https://here.r-lib.org/) package) 65 | 66 | * [Why?](https://www.tidyverse.org/articles/2017/12/workflow-vs-script/) 67 | 68 | 69 | 70 | #### Restart R many times each day 71 | 72 | Press Cmd/Ctrl + Shift + F10 to restart RStudio or go to _Session > Restart R_. 73 | 74 | #### Increase the rate limit to request downloads from GitHub 75 | 76 | See [`usethis::browse_github_pat()`](https://usethis.r-lib.org/reference/browse_github_pat.html). 77 | 78 | #### Prepare your system to build packages from source 79 | 80 | Sometimes you may need to install the _source_ version of an R package (e.g. from CRAN or GitHub). 81 | 82 | * [How?](https://usethis.r-lib.org/articles/articles/usethis-setup.html#prepare-your-system-to-build-packages-from-source) 83 | 84 | ## How to ask questions, report bugs, or propose features 85 | 86 | [Open a new issue](https://github.com/forestgeo/fgeo/issues/new) 87 | 88 | ## How to get help? 89 | 90 | ```R 91 | fgeo_help() 92 | ``` 93 | 94 | See also [Getting help with __fgeo__](https://forestgeo.github.io/fgeo/SUPPORT.html) or email Mauro Lepore (leporem\@si.edu). 95 | 96 | ## How to contribute to __fgeo__? 97 | 98 | See [Contributing to __fgeo__](https://forestgeo.github.io/fgeo/CONTRIBUTING.html). 99 | 100 | ## How to search functions and datasets 101 | 102 | See [Reference](https://forestgeo.github.io/fgeo/articles/siteonly/reference.html) 103 | 104 | ## How to search anything in ForestGEO GitHub's organization? 105 | 106 | GitHub's search engine is powerful. Go to and search anything. 107 | 108 | 109 | 110 | ## How to search the source code of a specific function? 111 | 112 | 1. Browse to the relevant package's website (e.g. [fgeo](https://forestgeo.github.io/fgeo/index.html)). 113 | 114 | 2. Find the function under _Reference_ (e.g. __fgeo__'s [Reference](https://forestgeo.github.io/fgeo/reference/index.html)). 115 | 116 | 3. Click the link to _Source_ under the topic's title. For example: 117 | 118 | 119 | 120 | ## How to search or share general resources with fgeo's community? 121 | 122 | Visit [forestgeo/learn](https://github.com/forestgeo/learn). 123 | 124 | ## How to discuss a general question with fgeo's community? 125 | 126 | Open a [New issue](https://github.com/forestgeo/forum/issues) at [forestgeo/forum](https://github.com/forestgeo/forum). 127 | 128 | ## How to try fgeo before installing it? 129 | 130 | Try __fgeo__ from your webrowser at . 131 | 132 | ## How to contact a human? 133 | 134 | Contact [__fgeo__'s maintainer](https://github.com/maurolepore). 135 | 136 | ## How to keep updated with __fgeo__'s developments? 137 | 138 | Checkout [__fgeo__'s blog](https://fgeo.netlify.com/). 139 | 140 | Follow [\@mauro_lepore](https://twitter.com/mauro_lepore) or [#fgeo #rstats on twitter](https://twitter.com/search?q=%23fgeo%20%23rstats&src=typd&lang=en) 141 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: fgeo 2 | Title: Analyze Forest Diversity and Dynamics 3 | Version: 1.1.4.9000 4 | Authors@R: 5 | c(person(given = "Mauro", 6 | family = "Lepore", 7 | role = c("aut", "ctr", "cre"), 8 | email = "maurolepore@gmail.com", 9 | comment = c(ORCID = "0000-0002-1986-7988")), 10 | person(given = "Gabriel", 11 | family = "Arellano", 12 | role = c("aut", "rev"), 13 | email = "gabriel.arellano.torres@gmail.com"), 14 | person(given = "Richard ", 15 | family = "Condit", 16 | role = "aut", 17 | email = "richardcondit@gmail.com"), 18 | person(given = "Stuart", 19 | family = "Davies", 20 | role = c("aut", "rev"), 21 | email = "daviess@si.edu"), 22 | person(given = "Matteo", 23 | family = "Detto", 24 | role = "aut", 25 | email = "teoparaglider@gmail.com"), 26 | person(given = "Erika", 27 | family = "Gonzalez-Akre", 28 | role = c("aut", "rev"), 29 | email = "GonzalezEB@si.edu", 30 | comment = c(ORCID = "0000-0001-8305-6672")), 31 | person(given = "Pamela", 32 | family = "Hall", 33 | role = "aut", 34 | email = "phall@alum.mit.edu"), 35 | person(given = "Kyle", 36 | family = "Harms", 37 | role = "aut", 38 | email = " kharms@lsu.edu"), 39 | person(given = "Valentine", 40 | family = "Herrmann", 41 | role = c("aut", "rev"), 42 | email = "HerrmannV@si.edu", 43 | comment = c(ORCID = "0000-0002-4519-481X")), 44 | person(given = "Aaron", 45 | family = "Hogan", 46 | role = "rev", 47 | email = "jamesaaronhogan@gmail.com", 48 | comment = c(ORCID = "0000-0001-9806-3074")), 49 | person(given = "Bier", 50 | family = "Kraichak", 51 | role = "rev", 52 | email = "ekraichak@gmail.com"), 53 | person(given = "David", 54 | family = "Kenfack", 55 | role = c("aut", "rev"), 56 | email = "KenfackD@si.edu "), 57 | person(given = "Lauren", 58 | family = "Krizel", 59 | role = "rev", 60 | email = "KrizelL@si.edu"), 61 | person(given = "Suzanne", 62 | family = "Lao", 63 | role = c("aut", "rev"), 64 | email = "laoz@si.edu"), 65 | person(given = "Sean", 66 | family = "McMahon", 67 | role = c("aut", "rev"), 68 | email = "mcmahons@si.edu"), 69 | person(given = "Haley", 70 | family = "Overstreet", 71 | role = "rev", 72 | email = "OverstreetH@si.edu"), 73 | person(given = "Sabrina", 74 | family = "Russo", 75 | role = c("aut", "rev"), 76 | email = "srusso2@unl.edu"), 77 | person(given = "Cara", 78 | family = "Scalpone", 79 | role = "rev", 80 | email = "ScalponeC@si.edu", 81 | comment = c(ORCID = "0000-0001-8448-2147")), 82 | person(given = "Kristina", 83 | family = "Anderson-Teixeira", 84 | role = c("aut", "rev"), 85 | email = "TeixeiraK@si.edu"), 86 | person(given = "Graham", 87 | family = "Zemunik", 88 | role = c("aut", "rev"), 89 | email = "grah.zem@gmail.com"), 90 | person(given = "Daniel", 91 | family = "Zuleta", 92 | role = c("aut", "rev"), 93 | email = "dfzuleta@gmail.com"), 94 | person(given = "CTFS-ForestGEO", 95 | role = c("cph", "fnd"), 96 | email = "ForestGEO@si.edu")) 97 | Description: To help you access, transform, analyze, and 98 | visualize ForestGEO data, we developed a collection of R packages 99 | (). This package, in particular, 100 | helps you to install and load the entire package-collection with a 101 | single R command, and provides convenient ways to find relevant 102 | documentation. Most commonly, you should not worry about the 103 | individual packages that make up the package-collection as you can 104 | access all features via this package. To learn more about ForestGEO 105 | visit . 106 | License: GPL-3 107 | URL: http://forestgeo.github.io/fgeo, 108 | https://github.com/forestgeo/fgeo 109 | BugReports: https://github.com/forestgeo/fgeo/issues 110 | Depends: 111 | R (>= 3.2) 112 | Imports: 113 | cli (>= 1.1.0), 114 | crayon (>= 1.3.4), 115 | dplyr (>= 0.8.1), 116 | fgeo.analyze (>= 1.1.10), 117 | fgeo.plot (>= 1.1.6), 118 | fgeo.tool (>= 1.2.4), 119 | fgeo.x (>= 1.1.3), 120 | glue (>= 1.3.1), 121 | magrittr (>= 1.5), 122 | purrr (>= 0.3.2), 123 | rlang (>= 0.3.4), 124 | rstudioapi (>= 0.10), 125 | utils 126 | Suggests: 127 | covr (>= 3.2.1), 128 | DT (>= 0.6), 129 | kableExtra (>= 1.1.0), 130 | knitr (>= 1.23), 131 | rmarkdown (>= 1.12), 132 | spelling (>= 2.1), 133 | testthat (>= 2.1.1) 134 | Encoding: UTF-8 135 | Language: en-US 136 | LazyData: true 137 | Roxygen: list(markdown = TRUE) 138 | RoxygenNote: 6.1.1 139 | -------------------------------------------------------------------------------- /.buildignore/fgeo.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Get started" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Get started} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r setup, include = FALSE} 11 | knitr::opts_chunk$set( 12 | eval = TRUE, 13 | echo = TRUE, 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | 18 | options(fgeo.quiet = TRUE) 19 | ``` 20 | 21 | This article shows some of the key features of __fgeo__ applied to an exploratory data analysis. For a deeper and general approach to exploratory data analysis, see [this book section](http://r4ds.had.co.nz/exploratory-data-analysis.html). A version adapted for ForestGEO is available [here](https://forestgeo.github.io/fgeo/articles/siteonly/eda.html). 22 | 23 | In every new R session you need to "open" __fgeo__ with `library()`. 24 | 25 | ```{r} 26 | library(fgeo) 27 | ``` 28 | 29 | You may suppress the start-up message with `suppressPackageStartupMessages()` or add `options("fgeo.quiet" = TRUE)` to .Rprofile (see [`usethis::edit_r_profile()`](https://usethis.r-lib.org/reference/edit.html)). 30 | 31 | You may use you own data but __fgeo__ comes with some example datasets. 32 | 33 | ```R 34 | fgeo_help("datasets") 35 | ``` 36 | 37 | We will start with a dataset of stems censused in one hectare from the forest plot in Luquillo, Puerto Rico (https://forestgeo.si.edu/sites/north-america/luquillo). 38 | 39 | ```{r} 40 | stem <- download_data("luquillo_stem_random") 41 | str(stem) 42 | ``` 43 | 44 | This dataset comes with multiple censuses but we will pick the latest one. 45 | 46 | ```{r} 47 | unique(stem$CensusID) 48 | 49 | stem <- filter(stem, CensusID %in% max(unique(stem$CensusID))) 50 | unique(stem$CensusID) 51 | ``` 52 | 53 | For a description of the columns, see `?data_dictionary`. 54 | 55 | ```{r} 56 | data_dictionary <- download_data("data_dictionary") 57 | str(data_dictionary) 58 | 59 | cols <- names(stem) 60 | filter(data_dictionary, column %in% cols) 61 | ``` 62 | 63 | ## Exploring the distribution of status and tree diameter 64 | 65 | Two columns that are commonly useful in ForestGEO datasets are `status` and `dbh` (diameter at breast height). We will begin by better understanding what type of variables they are. For this, base R provides useful functions. 66 | 67 | `status` is a categorical variable. 68 | 69 | ```{r} 70 | str(stem$status) 71 | ``` 72 | 73 | We can count the number of observations in each category with `table()`, then visualize the result with `barplot()`. 74 | 75 | ```{r} 76 | by_category <- table(stem$status) 77 | barplot(by_category) 78 | ``` 79 | 80 | `dbh` is a continuous numeric variable. 81 | 82 | ```{r} 83 | str(stem$dbh) 84 | ``` 85 | 86 | (Note the missing values (`NA`s).) 87 | 88 | And we can visualize its distribution with `hist()`. 89 | 90 | ```{r} 91 | hist(stem$dbh) 92 | ``` 93 | 94 | Unfortunately `hist()` dropped missing values silently. But we can better understand how missing values of `dbh` relate to `status` by extracting only the columns `dbh` and `status`, and picking only the rows where `dbh` is missing. 95 | 96 | ```{r} 97 | dbh_status <- stem[c("dbh", "status")] 98 | missing <- filter(dbh_status, is.na(dbh)) 99 | unique(missing) 100 | ``` 101 | 102 | Another approach is to count missing values. 103 | 104 | ```{r} 105 | missing <- transform(stem, na = ifelse(is.na(dbh), TRUE, FALSE)) 106 | table(missing$na, missing$status) 107 | ``` 108 | 109 | We learn that `dbh` is missing where a tree is dead (`status = D`) or gone (`status = G`). This makes sense and, depending on the type of analysis we want to do, we may want to keep or remove missing values. 110 | 111 | ## Determining tree status based on stem status 112 | 113 | Now we are ready to clean the data. For example, we can pick trees which status is "A" (alive). At ForestGEO, working with `status` is so common that __fgeo__ provides a specialized function. 114 | 115 | ```R 116 | fgeo_help("status") 117 | ``` 118 | 119 | In `stem`, the variable `status` records the status of each individual stem. How can we determine the status of a tree based on the status of each of its stems? That is the job of `add_status_tree()`. 120 | 121 | ```{r} 122 | stem <- add_status_tree(stem, status_a = "A", status_d = "D") 123 | alive_trees <- filter(stem, status_tree == "A") 124 | 125 | # Note that alive trees may have some missing, gone or dead stems 126 | some_cols <- c( "treeID", "status_tree", "stemID", "status") 127 | example_tree <- 46 128 | example_rows <- filter(alive_trees, treeID == example_tree) 129 | select(example_rows, some_cols) 130 | ``` 131 | 132 | ## Picking a `dbh` range 133 | 134 | Another very common task when working with ForestGEO data is to pick stems of a particular `dbh` range. 135 | 136 | ```R 137 | fgeo_help("dbh") 138 | ``` 139 | 140 | Pick stems of 10 mm or more. 141 | 142 | ```{r} 143 | ten_plus <- pick_dbh_min(alive_trees, 10) 144 | range(ten_plus$dbh, na.rm = TRUE) 145 | ``` 146 | 147 | ## Calculating abundance 148 | 149 | Calculate the total abundance of stems and trees. 150 | 151 | ```{r} 152 | # Drop missing values of `dbh` 153 | non_missing <- filter(ten_plus, !is.na(dbh)) 154 | 155 | # Stem abundance 156 | abundance(non_missing) 157 | 158 | # Tree abundance (picking main stems -- with highest `hom` and largest `dbh`) 159 | main_stems <- pick_main_stem(non_missing) 160 | abundance(main_stems) 161 | ``` 162 | 163 | Calculate the abundance of trees by species. 164 | 165 | ```{r} 166 | by_sp <- group_by(main_stems, sp) 167 | n_by_sp <- abundance(by_sp) 168 | n_by_sp 169 | ``` 170 | 171 | ## Picking the most abundant species 172 | 173 | What are the three most abundant tree species? 174 | 175 | ```{r} 176 | (top3_species <- arrange(n_by_sp, desc(n))[["sp"]][1:3]) 177 | ``` 178 | 179 | Now we can pick the `alive_trees` of only the `top3` species. 180 | 181 | ```{r} 182 | picked_stems <- filter(alive_trees, sp %in% top3_species) 183 | ``` 184 | 185 | ## Mapping the distribution of tree species 186 | 187 | __fgeo__ includes some functions specialized in mapping ForestGEO's data. 188 | 189 | ```R 190 | fgeo_help("map") 191 | ``` 192 | 193 | Map the most abundant species. 194 | 195 | ```{r} 196 | example_elevation <- fgeo.x::elevation 197 | 198 | species_elevation <- sp_elev(picked_stems, example_elevation) 199 | autoplot(species_elevation) 200 | ``` 201 | 202 | Tweak to focus on the hectare available in the data. 203 | 204 | ```{r} 205 | autoplot(species_elevation, xlim = c(100, 200), ylim = c(400, 500)) 206 | ``` 207 | 208 | 209 | 210 | ## Demography 211 | 212 | In this section we will use two other datasets. 213 | 214 | ```{r} 215 | census5 <- download_data("luquillo_tree5_random") 216 | census6 <- download_data("luquillo_tree6_random") 217 | 218 | recruitment_ctfs(census5, census6) 219 | ``` 220 | 221 | With `as_tibble()` we convert the result of any demography function to a tibble -- a convenient dataframe. 222 | 223 | ```{r} 224 | as_tibble( 225 | recruitment_ctfs(census5, census6) 226 | ) 227 | ``` 228 | 229 | We can aggregate results by any number of variables: 230 | 231 | * To aggregate by a single variable, you can pass the variable directly to `split1`. 232 | 233 | ```{r} 234 | as_tibble(recruitment_ctfs(census5, census6, split1 = census5$sp)) 235 | ``` 236 | 237 | * To aggregate by multiple variables, use `interaction()` (but aggregating by more than one variable may be slow and confusing). 238 | 239 | ```{r} 240 | sp_quadrat <- interaction(census5$sp, census5$quadrat) 241 | by_many <- recruitment_ctfs(census5, census6, split1 = sp_quadrat) 242 | as_tibble(by_many) 243 | ``` 244 | 245 | To separate the multiple groups we can use `tidyr::separate()`. 246 | 247 | ```{r} 248 | tidyr::separate(as_tibble(by_many), groups, into = c("species", "quadrats")) 249 | ``` 250 | 251 | The same works for mortality and growth. 252 | 253 | ```{r} 254 | as_tibble(mortality_ctfs(census5, census6, split1 = sp_quadrat)) 255 | 256 | as_tibble(growth_ctfs(census5, census6, split1 = sp_quadrat)) 257 | ``` 258 | 259 | ## Species-habitat associations 260 | 261 | In this section we will use a tree and elevation data, and we will create habitat data from the elevation data. 262 | 263 | ```{r} 264 | tree5 <- download_data("luquillo_tree5_random") 265 | elevation <- download_data("luquillo_elevation") 266 | 267 | # Pick alive trees, of 10 mm or more 268 | census <- filter(tree5, status == "A", dbh >= 10) 269 | 270 | # Pick sufficiently abundant species 271 | pick <- filter(add_count(census, sp), n > 50) 272 | 273 | # Use your habitat data or create it from elevation data 274 | habitat <- fgeo_habitat(elevation, gridsize = 20, n = 4) 275 | ``` 276 | 277 | We have everything we need. We can now calculate species-habitat associations with `tt_test()`. 278 | 279 | ```{r} 280 | # A list or matrices 281 | tt_test_result <- tt_test(pick, habitat) 282 | tt_test_result 283 | ``` 284 | 285 | Finally, here are some ways you may visualize the results. 286 | 287 | ```{r} 288 | # A simple summary to help you interpret the results 289 | summary(tt_test_result) 290 | 291 | # A combined matrix 292 | Reduce(rbind, tt_test_result) 293 | 294 | # A dataframe 295 | as_tibble(tt_test_result) 296 | ``` 297 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | editor_options: 4 | chunk_output_type: console 5 | --- 6 | 7 | 8 | ```{r, include = FALSE} 9 | knitr::opts_chunk$set( 10 | collapse = TRUE, 11 | fig.show = "hold", 12 | comment = "#>", 13 | fig.path = "man/figures/README-" 14 | ) 15 | ``` 16 | 17 | # Analyze forest diversity and dynamics 18 | 19 | 20 | [![lifecycle](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://www.tidyverse.org/lifecycle/#maturing) 21 | [![Travis build status](https://travis-ci.org/forestgeo/fgeo.svg?branch=master)](https://travis-ci.org/forestgeo/fgeo) 22 | [![Coverage status](https://codecov.io/gh/forestgeo/fgeo/branch/master/graph/badge.svg)](https://codecov.io/github/forestgeo/fgeo?branch=master) 23 | [![CRAN status](https://www.r-pkg.org/badges/version/fgeo)](https://cran.r-project.org/package=fgeo) 24 | 25 | 26 | ```{r, echo=FALSE} 27 | # Creates a functional link when used with DT table. 28 | fgeo_link <- function(package, topic = NULL) { 29 | end <- glue::glue(">{package}") 30 | if (!is.null(topic)) {end <- glue::glue("/reference/>{topic}")} 31 | glue::glue("") 32 | } 33 | 34 | link_core <- function(pattern) { 35 | core <- fgeo_to_attach()() 36 | fgeo_link(core[grepl(pattern, core)]) 37 | } 38 | 39 | analyze <- "analyze" 40 | visualize <- "map" 41 | manipulate <- "tool" 42 | datasets <- "x" 43 | ``` 44 | 45 | __fgeo__ helps you to install, load, and access the documentation of multiple packages to analyze forest diversity and dynamics (`r purrr::map_chr(fgeo::fgeo_packages(include_self = FALSE), fgeo_link)`). This package-collection allows you to manipulate and plot [ForestGEO](http://www.forestgeo.si.edu/) data, and to do common analyses including abundance, demography, and species-habitats associations. 46 | 47 | * [Search functions and datasets](https://forestgeo.github.io/fgeo/articles/siteonly/reference.html) 48 | * [Ask questions, report bugs, or propose features](https://github.com/forestgeo/fgeo/issues/new) 49 | 50 | ## Installation 51 | 52 | Make sure your R environment is as follows: 53 | 54 | * R version is recent 55 | * All packages are updated (run `update.packages()`; maybe use `ask = FALSE`) 56 | * No other R session is running 57 | * Current R session is clean (click _Session > Restart R_) 58 | 59 | Install the latest stable version of __fgeo__ from [CRAN](https://cran.r-project.org/) with: 60 | 61 | ```R 62 | install.packages("fgeo") 63 | ``` 64 | 65 | Or install the development version of __fgeo__ from [GitHub](https://github.com/) with: 66 | 67 | ```R 68 | # install.packages("devtools") 69 | devtools::install_github("forestgeo/fgeo.x") 70 | ``` 71 | 72 | * [How to setup .Rprofile for easiest installation of __fgeo__?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-setup--rprofile-for-easiest-installation-of-fgeo) 73 | * [How to update __fgeo__?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-update-fgeo) 74 | * [How to remove __fgeo__?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-remove-fgeo) 75 | * [How to avoid or fix common installation problems?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-avoid-or-fix-common-installation-problems) 76 | 77 | ## Example 78 | 79 | ```{r example} 80 | library(fgeo) 81 | ``` 82 | 83 | ### Explore __fgeo__ 84 | 85 | On an interactive session, `fgeo_help()` and `fgeo_browse_reference()` help you to search documentation. 86 | 87 | ``` 88 | if (interactive()) { 89 | # To search on the viewer; accepts keywords 90 | fgeo_help() 91 | # To search on a web browser 92 | fgeo_browse_reference() 93 | } 94 | ``` 95 | 96 | ### Access and manipulate data 97 | 98 | `example_path()` allows you to access datasets stored in your R libraries. 99 | 100 | ```{r} 101 | example_path() 102 | 103 | (vft_file <- example_path("view/vft_4quad.csv")) 104 | ``` 105 | 106 | #### `read_()` 107 | 108 | `read_vft()` and `read_taxa()` import a ViewFullTable and ViewTaxonomy from .tsv or .csv files. 109 | 110 | ```{r} 111 | read_vft(vft_file) 112 | ``` 113 | 114 | #### `pick_()` and `drop_()` 115 | 116 | __fgeo__ is pipe-friendly. You may not use pipes but often they make code easier to read. 117 | 118 | > Use %>% to emphasize a sequence of actions, rather than the object that the actions are being performed on. 119 | 120 | -- 121 | 122 | `pick_dbh_under()`, `drop_status()` and friends pick and drop rows from a ForestGEO ViewFullTable or census table. 123 | 124 | ```{r} 125 | (census <- fgeo.x::tree5) 126 | 127 | census %>% 128 | pick_dbh_under(100) 129 | ``` 130 | 131 | `pick_main_stem()` and `pick_main_stemid()` pick the main stem or main stemid(s) of each tree in each census. 132 | 133 | ```{r} 134 | stem <- download_data("luquillo_stem6_random") 135 | 136 | dim(stem) 137 | dim(pick_main_stem(stem)) 138 | ``` 139 | 140 | #### `add_()` 141 | 142 | `add_status_tree()`adds the column `status_tree` based on the status of all stems of each tree. 143 | 144 | ```{r} 145 | stem %>% 146 | select(CensusID, treeID, stemID, status) %>% 147 | add_status_tree() 148 | ``` 149 | 150 | `add_index()` and friends add columns to a ForestGEO-like dataframe. 151 | 152 | ```{r} 153 | stem %>% 154 | select(gx, gy) %>% 155 | add_index() 156 | ``` 157 | 158 | ### Plot data 159 | 160 | For simplicity, we will focus on only a few species. 161 | 162 | ```{r} 163 | stem_2sp <- stem %>% 164 | filter(sp %in% c("PREMON", "CASARB")) 165 | ``` 166 | 167 | `autoplot()` and friends produce different output depending on the class of input. You can create different input classes, for example, with `sp()` and `sp_elev()`: 168 | 169 | * Use `sp(census)` to plot the column `sp` of a `census` dataset -- i.e. to plot species distribution. 170 | 171 | ```{r autoplot-sp} 172 | class(sp(stem_2sp)) 173 | 174 | autoplot(sp(stem_2sp)) 175 | ``` 176 | 177 | * Use `sp_elev(census, elevation)` to plot the columns `sp` and `elev` of a `census` and `elevation` dataset, respectively -- i.e. to plot species distribution and topography. 178 | 179 | ```{r autoplot-sp-elev} 180 | elevation <- fgeo.x::elevation 181 | class(sp_elev(stem_2sp, elevation)) 182 | 183 | autoplot(sp_elev(stem_2sp, elevation)) 184 | ``` 185 | 186 | ### Analyze 187 | 188 | #### Abundance 189 | 190 | `abundance()` and `basal_area()` calculate abundance and basal area, optionally by groups. 191 | 192 | ```{r} 193 | abundance( 194 | pick_main_stem(census) 195 | ) 196 | 197 | by_species <- group_by(census, sp) 198 | 199 | basal_area(by_species) 200 | ``` 201 | 202 | #### Demography 203 | 204 | `recruitment_ctfs()`, `mortality_ctfs()`, and `growth_ctfs()` calculate recruitment, mortality, and growth. They all output a list. `as_tibble()` converts the output from a list to a more convenient dataframe. 205 | 206 | ```{r} 207 | tree5 <- fgeo.x::tree5 208 | 209 | as_tibble( 210 | mortality_ctfs(tree5, tree6) 211 | ) 212 | ``` 213 | 214 | #### Species-habitats association 215 | 216 | `tt_test()` runs a torus translation test to determine habitat associations of tree species. `as_tibble()` converts the output from a list to a more convenient dataframe. `summary()` helps you to interpret the result. 217 | 218 | ```{r} 219 | # This analysis makes sense only for tree tables 220 | tree <- download_data("luquillo_tree5_random") 221 | 222 | habitat <- fgeo.x::habitat 223 | result <- tt_test(tree, habitat) 224 | 225 | as_tibble(result) 226 | 227 | summary(result) 228 | ``` 229 | 230 | ## Downloads of fgeo packages 231 | 232 | ```{r fgeo-downloads, echo=FALSE, message=FALSE, warning=FALSE} 233 | library(ggplot2) 234 | 235 | fgeo::fgeo_packages() %>% 236 | cranlogs::cran_downloads(from = "2019-05-09", to = lubridate::today()) %>% 237 | ggplot(aes(date, count)) + 238 | geom_col() + 239 | labs(caption = "Data from ") 240 | ``` 241 | 242 | ## Related projects 243 | 244 | Additional packages maintained by ForestGEO but not included in __fgeo__: 245 | 246 | * [__fgeo.data__](https://forestgeo.github.io/fgeo.data/): Open datasets of ForestGEO. 247 | * [__fgeo.krig__](https://forestgeo.github.io/fgeo.krig/): Analyze soils. 248 | 249 | Other packages not maintained by ForestGEO: 250 | 251 | * [CTFS-R Package](http://ctfs.si.edu/Public/CTFSRPackage/): The original package of CTFS functions. No longer supported by ForestGEO. 252 | * [__BIOMASS__](https://CRAN.R-project.org/package=BIOMASS): An R package to estimate above-ground biomass in tropical forests. 253 | 254 | ## R code from recent publications by ForestGEO partners 255 | 256 | Data have been made available as required by the journal to enable reproduction of the results presented in the paper. Please do not share these data without permission of the ForestGEO plot Principal Investigators (PIs). If you wish to publish papers based on these data, you are also required to get permission from the PIs of the corresponding ForestGEO plots. 257 | 258 | * [Disentangling fire intensity and species' susceptibility to fire in a species-rich seasonal tropical forest (Trouve et al., 2019).](https://github.com/forestgeo/Trouve_et_al_2019) 259 | 260 | * [Soil drivers of local-scale tree growth in a lowland tropical forest (Zemunik et al., 2018).](https://github.com/SoilLabAtSTRI/Soil-drivers-of-tree-growth) 261 | 262 | * [Plant diversity increases with the strength of negative density dependence at the global scale (LaManna et al., 2018)](https://github.com/forestgeo/LaManna_et_al_Science) 263 | * Response #1: LaManna et al. 2018. Response to Comment on "Plant diversity increases with the strength of negative density dependence at the global scale" Science Vol. 360, Issue 6391, eaar3824. DOI: 10.1126/science.aar3824 264 | * Response #2: LaManna et al. 2018. Response to Comment on "Plant diversity increases with the strength of negative density dependence at the global scale". Science Vol. 360, Issue 6391, eaar5245. DOI: 10.1126/science.aar5245 265 | 266 | ## Information 267 | 268 | * [Getting help](https://forestgeo.github.io/fgeo/SUPPORT.html). 269 | * [Contributing](https://forestgeo.github.io/fgeo/CONTRIBUTING.html). 270 | * [Contributor Code of Conduct](https://forestgeo.github.io/fgeo/CODE_OF_CONDUCT.html). 271 | 272 | ## Acknowledgments 273 | 274 | Thanks to all partners of ForestGEO for sharing their ideas and code. For feedback on __fgeo__, special thanks to Gabriel Arellano, Stuart Davies, Lauren Krizel, Sean McMahon, and Haley Overstreet. For all other help, I thank contributors in the documentation of the features they helped with. 275 | 276 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Analyze forest diversity and dynamics 5 | 6 | 7 | 8 | [![lifecycle](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://www.tidyverse.org/lifecycle/#maturing) 9 | [![Travis build 10 | status](https://travis-ci.org/forestgeo/fgeo.svg?branch=master)](https://travis-ci.org/forestgeo/fgeo) 11 | [![Coverage 12 | status](https://codecov.io/gh/forestgeo/fgeo/branch/master/graph/badge.svg)](https://codecov.io/github/forestgeo/fgeo?branch=master) 13 | [![CRAN 14 | status](https://www.r-pkg.org/badges/version/fgeo)](https://cran.r-project.org/package=fgeo) 15 | 16 | 17 | **fgeo** helps you to install, load, and access the documentation of 18 | multiple packages to analyze forest diversity and dynamics 19 | (fgeo.analyze, 20 | fgeo.plot, 21 | fgeo.tool, 22 | fgeo.x). This 23 | package-collection allows you to manipulate and plot 24 | [ForestGEO](http://www.forestgeo.si.edu/) data, and to do common 25 | analyses including abundance, demography, and species-habitats 26 | associations. 27 | 28 | - [Search functions and 29 | datasets](https://forestgeo.github.io/fgeo/articles/siteonly/reference.html) 30 | - [Ask questions, report bugs, or propose 31 | features](https://github.com/forestgeo/fgeo/issues/new) 32 | 33 | ## Installation 34 | 35 | Make sure your R environment is as follows: 36 | 37 | - R version is recent 38 | - All packages are updated (run `update.packages()`; maybe use `ask = 39 | FALSE`) 40 | - No other R session is running 41 | - Current R session is clean (click *Session \> Restart R*) 42 | 43 | Install the latest stable version of **fgeo** from 44 | [CRAN](https://cran.r-project.org/) with: 45 | 46 | ``` r 47 | install.packages("fgeo") 48 | ``` 49 | 50 | Or install the development version of **fgeo** from 51 | [GitHub](https://github.com/) with: 52 | 53 | ``` r 54 | # install.packages("devtools") 55 | devtools::install_github("forestgeo/fgeo.x") 56 | ``` 57 | 58 | - [How to setup .Rprofile for easiest installation of 59 | **fgeo**?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-setup--rprofile-for-easiest-installation-of-fgeo) 60 | - [How to update 61 | **fgeo**?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-update-fgeo) 62 | - [How to remove 63 | **fgeo**?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-remove-fgeo) 64 | - [How to avoid or fix common installation 65 | problems?](https://forestgeo.github.io/fgeo/articles/siteonly/questions-and-answers.html#how-to-avoid-or-fix-common-installation-problems) 66 | 67 | ## Example 68 | 69 | ``` r 70 | library(fgeo) 71 | #> ── Attaching packages ────────────────────────────────────────── fgeo 1.1.3.9000 ── 72 | #> ✔ fgeo.analyze 1.1.10.9000 ✔ fgeo.tool 1.2.5 73 | #> ✔ fgeo.plot 1.1.8 ✔ fgeo.x 1.1.4 74 | #> ── Conflicts ────────────────────────────────────────────────── fgeo_conflicts() ── 75 | #> ✖ fgeo.tool::filter() masks stats::filter() 76 | ``` 77 | 78 | ### Explore **fgeo** 79 | 80 | On an interactive session, `fgeo_help()` and `fgeo_browse_reference()` 81 | help you to search documentation. 82 | 83 | if (interactive()) { 84 | # To search on the viewer; accepts keywords 85 | fgeo_help() 86 | # To search on a web browser 87 | fgeo_browse_reference() 88 | } 89 | 90 | ### Access and manipulate data 91 | 92 | `example_path()` allows you to access datasets stored in your R 93 | libraries. 94 | 95 | ``` r 96 | example_path() 97 | #> [1] "csv" "mixed_files" "rdata" "rdata_one" 98 | #> [5] "rds" "taxa.csv" "tsv" "vft_4quad.csv" 99 | #> [9] "view" "weird" "xl" 100 | 101 | (vft_file <- example_path("view/vft_4quad.csv")) 102 | #> [1] "/home/mauro/R/x86_64-pc-linux-gnu-library/3.6/fgeo.x/extdata/view/vft_4quad.csv" 103 | ``` 104 | 105 | #### `read_
()` 106 | 107 | `read_vft()` and `read_taxa()` import a ViewFullTable and ViewTaxonomy 108 | from .tsv or .csv files. 109 | 110 | ``` r 111 | read_vft(vft_file) 112 | #> # A tibble: 500 x 32 113 | #> DBHID PlotName PlotID Family Genus SpeciesName Mnemonic Subspecies 114 | #> 115 | #> 1 385164 luquillo 1 Rubia… Psyc… brachiata PSYBRA 116 | #> 2 385261 luquillo 1 Urtic… Cecr… schreberia… CECSCH 117 | #> 3 384600 luquillo 1 Rubia… Psyc… brachiata PSYBRA 118 | #> 4 608789 luquillo 1 Rubia… Psyc… berteroana PSYBER 119 | #> 5 388579 luquillo 1 Areca… Pres… acuminata PREMON 120 | #> 6 384626 luquillo 1 Arali… Sche… morototoni SCHMOR 121 | #> 7 410958 luquillo 1 Rubia… Psyc… brachiata PSYBRA 122 | #> 8 385102 luquillo 1 Piper… Piper glabrescens PIPGLA 123 | #> 9 353163 luquillo 1 Areca… Pres… acuminata PREMON 124 | #> 10 481018 luquillo 1 Salic… Case… arborea CASARB 125 | #> # … with 490 more rows, and 24 more variables: SpeciesID , 126 | #> # SubspeciesID , QuadratName , QuadratID , PX , 127 | #> # PY , QX , QY , TreeID , Tag , StemID , 128 | #> # StemNumber , StemTag , PrimaryStem , CensusID , 129 | #> # PlotCensusNumber , DBH , HOM , ExactDate , 130 | #> # Date , ListOfTSM , HighHOM , LargeStem , 131 | #> # Status 132 | ``` 133 | 134 | #### `pick_()` and `drop_()` 135 | 136 | **fgeo** is pipe-friendly. You may not use pipes but often they make 137 | code easier to read. 138 | 139 | > Use %\>% to emphasize a sequence of actions, rather than the object 140 | > that the actions are being performed on. 141 | 142 | – 143 | 144 | `pick_dbh_under()`, `drop_status()` and friends pick and drop rows from 145 | a ForestGEO ViewFullTable or census table. 146 | 147 | ``` r 148 | (census <- fgeo.x::tree5) 149 | #> # A tibble: 30 x 19 150 | #> treeID stemID tag StemTag sp quadrat gx gy MeasureID CensusID 151 | #> 152 | #> 1 7624 160987 1089… 175325 TRIP… 722 139. 425. 486675 5 153 | #> 2 8055 10036 1094… 109482 CECS… 522 94.8 424. 468874 5 154 | #> 3 19930 117849 1234… 165576 CASA… 425 61.3 496. 471979 5 155 | #> 4 23746 29677 14473 14473 PREM… 617 100. 328. 442571 5 156 | #> 5 31702 39793 22889 22889 SLOB… 304 53.8 73.8 447307 5 157 | #> 6 35355 44026 27538 27538 SLOB… 1106 203. 110. 449169 5 158 | #> 7 35891 44634 282 282 DACE… 901 172. 14.7 434266 5 159 | #> 8 39705 48888 33371 33370 CASS… 1010 184. 194. 451067 5 160 | #> 9 50184 60798 5830 5830 MATD… 1007 191. 132. 437645 5 161 | #> 10 57380 155867 66962 171649 SLOB… 1414 274. 279. 459427 5 162 | #> # … with 20 more rows, and 9 more variables: dbh , pom , 163 | #> # hom , ExactDate , DFstatus , codes , 164 | #> # nostems , status , date 165 | 166 | census %>% 167 | pick_dbh_under(100) 168 | #> # A tibble: 18 x 19 169 | #> treeID stemID tag StemTag sp quadrat gx gy MeasureID CensusID 170 | #> 171 | #> 1 7624 160987 1089… 175325 TRIP… 722 139. 425. 486675 5 172 | #> 2 19930 117849 1234… 165576 CASA… 425 61.3 496. 471979 5 173 | #> 3 31702 39793 22889 22889 SLOB… 304 53.8 73.8 447307 5 174 | #> 4 35355 44026 27538 27538 SLOB… 1106 203. 110. 449169 5 175 | #> 5 39705 48888 33371 33370 CASS… 1010 184. 194. 451067 5 176 | #> 6 57380 155867 66962 171649 SLOB… 1414 274. 279. 459427 5 177 | #> 7 95656 129113 1315… 131519 OCOL… 402 79.7 22.8 474157 5 178 | #> 8 96051 129565 1323… 132348 HIRR… 1403 278 40.6 474523 5 179 | #> 9 96963 130553 1347… 134707 TETB… 610 114. 182. 475236 5 180 | #> 10 115310 150789 1652… 165286 MANB… 225 24.0 497. 483175 5 181 | #> 11 121424 158579 1707… 170701 CASS… 811 146. 218. 484785 5 182 | #> 12 121689 158871 1712… 171277 INGL… 515 84.2 285. 485077 5 183 | #> 13 121953 159139 1718… 171809 PSYB… 1318 247. 354. 485345 5 184 | #> 14 124522 162698 1742… 174224 CASS… 1411 279. 210. 488386 5 185 | #> 15 125038 163236 1753… 175335 CASS… 822 153. 426. 488924 5 186 | #> 16 126087 NA 1773… CASA… 521 89.8 408. NA NA 187 | #> 17 126803 NA 1785… PSYB… 622 113. 426 NA NA 188 | #> 18 126934 NA 1787… MICR… 324 47 480. NA NA 189 | #> # … with 9 more variables: dbh , pom , hom , 190 | #> # ExactDate , DFstatus , codes , nostems , 191 | #> # status , date 192 | ``` 193 | 194 | `pick_main_stem()` and `pick_main_stemid()` pick the main stem or main 195 | stemid(s) of each tree in each census. 196 | 197 | ``` r 198 | stem <- download_data("luquillo_stem6_random") 199 | 200 | dim(stem) 201 | #> [1] 1320 19 202 | dim(pick_main_stem(stem)) 203 | #> [1] 1000 19 204 | ``` 205 | 206 | #### `add_()` 207 | 208 | `add_status_tree()`adds the column `status_tree` based on the status of 209 | all stems of each tree. 210 | 211 | ``` r 212 | stem %>% 213 | select(CensusID, treeID, stemID, status) %>% 214 | add_status_tree() 215 | #> # A tibble: 1,320 x 5 216 | #> CensusID treeID stemID status status_tree 217 | #> 218 | #> 1 6 104 143 A A 219 | #> 2 6 119 158 A A 220 | #> 3 NA 180 222 G A 221 | #> 4 NA 180 223 G A 222 | #> 5 6 180 224 G A 223 | #> 6 6 180 225 A A 224 | #> 7 6 602 736 A A 225 | #> 8 6 631 775 A A 226 | #> 9 6 647 793 A A 227 | #> 10 6 1086 1339 A A 228 | #> # … with 1,310 more rows 229 | ``` 230 | 231 | `add_index()` and friends add columns to a ForestGEO-like dataframe. 232 | 233 | ``` r 234 | stem %>% 235 | select(gx, gy) %>% 236 | add_index() 237 | #> Guessing: plotdim = c(320, 500) 238 | #> * If guess is wrong, provide the correct argument `plotdim` 239 | #> # A tibble: 1,320 x 3 240 | #> gx gy index 241 | #> 242 | #> 1 10.3 245. 13 243 | #> 2 183. 410. 246 244 | #> 3 165. 410. 221 245 | #> 4 165. 410. 221 246 | #> 5 165. 410. 221 247 | #> 6 165. 410. 221 248 | #> 7 149. 414. 196 249 | #> 8 38.3 245. 38 250 | #> 9 143. 411. 196 251 | #> 10 68.9 253. 88 252 | #> # … with 1,310 more rows 253 | ``` 254 | 255 | ### Plot data 256 | 257 | For simplicity, we will focus on only a few species. 258 | 259 | ``` r 260 | stem_2sp <- stem %>% 261 | filter(sp %in% c("PREMON", "CASARB")) 262 | ``` 263 | 264 | `autoplot()` and friends produce different output depending on the class 265 | of input. You can create different input classes, for example, with 266 | `sp()` and `sp_elev()`: 267 | 268 | - Use `sp(census)` to plot the column `sp` of a `census` dataset – 269 | i.e. to plot species distribution. 270 | 271 | 272 | 273 | ``` r 274 | class(sp(stem_2sp)) 275 | #> [1] "sp" "tbl_df" "tbl" "data.frame" 276 | 277 | autoplot(sp(stem_2sp)) 278 | ``` 279 | 280 | ![](man/figures/README-autoplot-sp-1.png) 281 | 282 | - Use `sp_elev(census, elevation)` to plot the columns `sp` and `elev` 283 | of a `census` and `elevation` dataset, respectively – i.e. to plot 284 | species distribution and topography. 285 | 286 | 287 | 288 | ``` r 289 | elevation <- fgeo.x::elevation 290 | class(sp_elev(stem_2sp, elevation)) 291 | #> [1] "sp_elev" "list" 292 | 293 | autoplot(sp_elev(stem_2sp, elevation)) 294 | ``` 295 | 296 | ![](man/figures/README-autoplot-sp-elev-1.png) 297 | 298 | ### Analyze 299 | 300 | #### Abundance 301 | 302 | `abundance()` and `basal_area()` calculate abundance and basal area, 303 | optionally by groups. 304 | 305 | ``` r 306 | abundance( 307 | pick_main_stem(census) 308 | ) 309 | #> # A tibble: 1 x 1 310 | #> n 311 | #> 312 | #> 1 30 313 | 314 | by_species <- group_by(census, sp) 315 | 316 | basal_area(by_species) 317 | #> # A tibble: 18 x 2 318 | #> # Groups: sp [18] 319 | #> sp basal_area 320 | #> 321 | #> 1 CASARB 437. 322 | #> 2 CASSYL 4146. 323 | #> 3 CECSCH 144150. 324 | #> 4 DACEXC 56832. 325 | #> 5 GUAGUI 9161. 326 | #> 6 HIRRUG 131. 327 | #> 7 INGLAU 141. 328 | #> 8 MANBID 167. 329 | #> 9 MATDOM 45239. 330 | #> 10 MICRAC 0 331 | #> 11 OCOLEU 437. 332 | #> 12 PREMON 78864. 333 | #> 13 PSYBER 0 334 | #> 14 PSYBRA 154. 335 | #> 15 SCHMOR 41187. 336 | #> 16 SLOBER 23377. 337 | #> 17 TETBAL 272. 338 | #> 18 TRIPAL 93.3 339 | ``` 340 | 341 | #### Demography 342 | 343 | `recruitment_ctfs()`, `mortality_ctfs()`, and `growth_ctfs()` calculate 344 | recruitment, mortality, and growth. They all output a list. 345 | `as_tibble()` converts the output from a list to a more convenient 346 | dataframe. 347 | 348 | ``` r 349 | tree5 <- fgeo.x::tree5 350 | 351 | as_tibble( 352 | mortality_ctfs(tree5, tree6) 353 | ) 354 | #> Detected dbh ranges: 355 | #> * `census1` = 10.9-323. 356 | #> * `census2` = 10.5-347. 357 | #> Using dbh `mindbh = 0` and above. 358 | #> # A tibble: 1 x 9 359 | #> N D rate lower upper time date1 date2 dbhmean 360 | #> 361 | #> 1 27 1 0.00834 0.00195 0.0448 4.52 18938. 20590. 101. 362 | ``` 363 | 364 | #### Species-habitats association 365 | 366 | `tt_test()` runs a torus translation test to determine habitat 367 | associations of tree species. `as_tibble()` converts the output from a 368 | list to a more convenient dataframe. `summary()` helps you to interpret 369 | the result. 370 | 371 | ``` r 372 | # This analysis makes sense only for tree tables 373 | tree <- download_data("luquillo_tree5_random") 374 | 375 | habitat <- fgeo.x::habitat 376 | result <- tt_test(tree, habitat) 377 | #> Using `plotdim = c(320, 500)`. To change this value see `?tt_test()`. 378 | #> Using `gridsize = 20`. To change this value see `?tt_test()`. 379 | 380 | as_tibble(result) 381 | #> # A tibble: 292 x 8 382 | #> habitat sp N.Hab Gr.Hab Ls.Hab Eq.Hab Rep.Agg.Neut Obs.Quantile 383 | #> * 384 | #> 1 1 ALCFLO 2 1443 153 4 0 0.902 385 | #> 2 2 ALCFLO 1 807 778 15 0 0.504 386 | #> 3 3 ALCFLO 0 0 715 885 -1 0 387 | #> 4 4 ALCFLO 0 0 402 1198 -1 0 388 | #> 5 1 ALCLAT 0 0 544 1056 -1 0 389 | #> 6 2 ALCLAT 1 1432 156 12 0 0.895 390 | #> 7 3 ALCLAT 0 0 324 1276 -1 0 391 | #> 8 4 ALCLAT 0 0 144 1456 -1 0 392 | #> 9 1 ANDINE 1 1117 466 17 0 0.698 393 | #> 10 2 ANDINE 1 1081 510 9 0 0.676 394 | #> # … with 282 more rows 395 | 396 | summary(result) 397 | #> # A tibble: 292 x 3 398 | #> sp habitat association 399 | #> 400 | #> 1 ALCFLO 1 neutral 401 | #> 2 ALCFLO 2 neutral 402 | #> 3 ALCFLO 3 repelled 403 | #> 4 ALCFLO 4 repelled 404 | #> 5 ALCLAT 1 repelled 405 | #> 6 ALCLAT 2 neutral 406 | #> 7 ALCLAT 3 repelled 407 | #> 8 ALCLAT 4 repelled 408 | #> 9 ANDINE 1 neutral 409 | #> 10 ANDINE 2 neutral 410 | #> # … with 282 more rows 411 | ``` 412 | 413 | ## Downloads of fgeo packages 414 | 415 | ![](man/figures/README-fgeo-downloads-1.png) 416 | 417 | ## Related projects 418 | 419 | Additional packages maintained by ForestGEO but not included in 420 | **fgeo**: 421 | 422 | - [**fgeo.data**](https://forestgeo.github.io/fgeo.data/): Open 423 | datasets of ForestGEO. 424 | - [**fgeo.krig**](https://forestgeo.github.io/fgeo.krig/): Analyze 425 | soils. 426 | 427 | Other packages not maintained by ForestGEO: 428 | 429 | - [CTFS-R Package](http://ctfs.si.edu/Public/CTFSRPackage/): The 430 | original package of CTFS functions. No longer supported by 431 | ForestGEO. 432 | - [**BIOMASS**](https://CRAN.R-project.org/package=BIOMASS): An R 433 | package to estimate above-ground biomass in tropical forests. 434 | 435 | ## R code from recent publications by ForestGEO partners 436 | 437 | Data have been made available as required by the journal to enable 438 | reproduction of the results presented in the paper. Please do not share 439 | these data without permission of the ForestGEO plot Principal 440 | Investigators (PIs). If you wish to publish papers based on these data, 441 | you are also required to get permission from the PIs of the 442 | corresponding ForestGEO plots. 443 | 444 | - [Soil drivers of local-scale tree growth in a lowland tropical 445 | forest (Zemunik et 446 | al., 2018).](https://github.com/SoilLabAtSTRI/Soil-drivers-of-tree-growth) 447 | - [Plant diversity increases with the strength of negative density 448 | dependence at the global scale (LaManna et 449 | al., 2018)](https://github.com/forestgeo/LaManna_et_al_Science) 450 | - Response \#1: LaManna et al. 2018. Response to Comment on “Plant 451 | diversity increases with the strength of negative density 452 | dependence at the global scale” Science Vol. 360, Issue 6391, 453 | eaar3824. DOI: 10.1126/science.aar3824 454 | - Response \#2: LaManna et al. 2018. Response to Comment on “Plant 455 | diversity increases with the strength of negative density 456 | dependence at the global scale”. Science Vol. 360, Issue 6391, 457 | eaar5245. DOI: 10.1126/science.aar5245 458 | 459 | ## Information 460 | 461 | - [Getting help](https://forestgeo.github.io/fgeo/SUPPORT.html). 462 | - [Contributing](https://forestgeo.github.io/fgeo/CONTRIBUTING.html). 463 | - [Contributor Code of 464 | Conduct](https://forestgeo.github.io/fgeo/CODE_OF_CONDUCT.html). 465 | 466 | ## Acknowledgments 467 | 468 | Thanks to all partners of ForestGEO for sharing their ideas and code. 469 | For feedback on **fgeo**, special thanks to Gabriel Arellano, Stuart 470 | Davies, Lauren Krizel, Sean McMahon, and Haley Overstreet. For all other 471 | help, I thank contributors in the the documentation of the features they 472 | helped with. 473 | -------------------------------------------------------------------------------- /.buildignore/eda.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Exploratory Data Analysis" 3 | subtitle: Adapted for [ForestGEO](https://twitter.com/ForestGEO?lang=en) from [R for Data Science](http://r4ds.had.co.nz/), by [Hadley Wickham](https://twitter.com/hadleywickham) and [Garrett Grolemund](https://twitter.com/StatGarrett) 4 | author: "Mauro Lepore" 5 | date: "`r Sys.Date()`" 6 | output: rmarkdown::html_vignette 7 | --- 8 | 9 | ```{r setup, include = FALSE} 10 | knitr::opts_chunk$set( 11 | collapse = TRUE, 12 | eval = TRUE, 13 | comment = "#>", 14 | fig.show = "hold", 15 | fig.align = "center", 16 | out.width = "70%", 17 | fig.width = 9.5, 18 | fig.asp = 0.7 19 | ) 20 | ``` 21 | 22 | Here, I reproduce the section _Exploratory Data Analysis_ of the book _R for Data Science_ (http://r4ds.had.co.nz/), by Hadley Wickham and Garrett Grolemund -- except for the examples and some text, which I changed to engage ecologists from ForestGEO. 23 | 24 | # Introduction 25 | 26 | This article will show you how to explore your data with general purpose tools, mostly from the __tidyverse__ (https://www.tidyverse.org/). This is a good place to start before you learn the specific tools from the __fgeo__ package (https://forestgeo.github.io/fgeo/). For an exploratory data analysis with __fgeo__, see [Get Started](https://forestgeo.github.io/fgeo/articles/fgeo.html#get-started). 27 | 28 | You will learn to explore your data systematically by using modern and powerful tools for visualization and transformation. An exploratory data analysis is an iterative process that aims to use data and some research questions to learn something that can help you refine those questions and move forward along the learning spiral. 29 | 30 | If you are new to the __tidyverse__, you may feel a little frustrated at the beginning, but your effort will quickly pay-off. The tools in the __tidyverse__ are powerful, relatively easy to use, and consistent; so once you learn some of the tools, you will learn most other tools intuitively. 31 | 32 | ```{r, eval=TRUE} 33 | library(tidyverse) 34 | ``` 35 | 36 | We will use the dataset `luquillo_stem_random` from the __fgeo.data__ package (https://forestgeo.github.io/fgeo.data/), which records trees censused in a forest plot in Luquillo, Puerto Rico. 37 | 38 | ```{r, eval=TRUE} 39 | # Convenient nickname 40 | stem <- fgeo.x::download_data("luquillo_stem_random") 41 | ``` 42 | 43 | ## Style 44 | 45 | ### The tidyverse style guide 46 | 47 | The code style I use here follows the tidyverse guide (http://style.tidyverse.org/). 48 | 49 | > Good coding style is like correct punctuation: you can manage without it, butitsuremakesthingseasiertoread. 50 | 51 | ### Combining multiple operations with the pipe %>% 52 | 53 | Often I combine multiple operations with the pipe `%>%`, because it makes the code considerably more readable. 54 | 55 | > [The pipe] focuses on the transformations, not what's being transformed, which makes the code easier to read. You can read it as a series of imperative statements: group, then summarise, then filter. As suggested by this reading, a good way to pronounce %>% when reading code is "then". 56 | 57 | > Behind the scenes, `x %>% f(y)` turns into `f(x, y)`, and `x %>% f(y) %>% g(z)` turns into `g(f(x, y), z)` and so on. You can use the pipe to rewrite multiple operations in a way that you can read left-to-right, top-to-bottom. 58 | 59 | > Working with the pipe is one of the key criteria for belonging to the tidyverse. The only exception is ggplot2: it was written before the pipe was discovered. 60 | 61 | –- R for Data Science (http://r4ds.had.co.nz/transform.html) 62 | 63 | # Questions and definitions 64 | 65 | ## Questions 66 | 67 | To start exploring your data, you can generally ask these questions: 68 | 69 | * What type of variation occurs within my variables? 70 | * What type of covariation occurs between my variables? 71 | 72 | ## Definitions 73 | 74 | A __variable__ is a quantity, quality, or property that you can measure. 75 | 76 | A __value__ is the state of a variable when you measure it. The value of a variable may change from measurement to measurement. 77 | 78 | An __observation__ is a set of measurements made under similar conditions (you usually make all of the measurements in an observation at the same time and on the same object). An observation will contain several values, each associated with a different variable. I will sometimes refer to an observation as a data point. 79 | 80 | __Tabular data__ is a set of values, each associated with a variable and an observation. Tabular data is tidy if each value is placed in its own “cell”, each variable in its own column, and each observation in its own row. 81 | 82 | __Variation__ is the tendency of the values of a variable to change from measurement to measurement. 83 | 84 | # Variation 85 | 86 | Every variable varies with a particular pattern, and that pattern may be insightful. To understand the variation pattern of a variable, we can visualize the distribution of the variables' values. The best way to visualize a variable's distribution depends on whether the variable is categorical or continuous. 87 | 88 | The `stem` dataset has both categorical and continuous variables. In R, categorical variables are usually stored as character strings (``) or factors (``), and continuous variables are stored as integers (``) or doubles (``). 89 | 90 | `stem` is a tibble. A tibble is a subclass of dataframe. But compared to regular dataframes, tibbles are optimized to handle large data; they also print more information and show it in a nicer way. 91 | 92 | ```{r, eval=TRUE} 93 | class(stem) 94 | 95 | stem 96 | ``` 97 | 98 | By default, tibbles print a few rows only; to print more rows use: 99 | 100 | ```R 101 | print(, n = , width = ) 102 | ``` 103 | 104 | You can always convert a tibble into a regular dataframe. 105 | 106 | ```R 107 | # This is ackward because it prints way more than you can fit on a screen 108 | as.data.frame(stem) 109 | ``` 110 | 111 | For alternative views try: 112 | 113 | ```{r} 114 | # informative and prints nice 115 | str(stem) 116 | # like str() but shows as much data as possible 117 | glimpse(stem) 118 | ``` 119 | 120 | If you are in RStudio, your best option might be `View()`, which lets you search values and filter columns. 121 | 122 | ```R 123 | View(stem) 124 | ``` 125 | 126 | 127 | 128 | ## Visualizing distributions 129 | 130 | ### Categorical variables 131 | 132 | A variable is categorical if it can only take one of a small set of values. To examine the distribution of a categorical variable, use a bar chart. 133 | 134 | ```{r} 135 | ggplot(data = stem) + 136 | geom_bar(mapping = aes(x = status)) 137 | ``` 138 | 139 | The categories A, D and M, of the variable `status` mean "alive", "dead" and "missing" (http://ctfs.si.edu/Public/DataDict/data_dict.php). 140 | 141 | ### Continuous variables 142 | 143 | A variable is continuous if it can take any of an infinite set of ordered values. To examine the distribution of a continuous variable, use a histogram. You should always explore a variety of binwidths when working with histograms, as different binwidths can reveal different patterns. 144 | 145 | Let's explore `dbh`, which represents the stem diameter at breast height. Now we will focus on small stems; we will explore big stems later. And we will try bars of different widths (with `binwidth`) and choose one for further analyses. 146 | 147 | ```{r} 148 | small_dbh <- filter(stem, dbh < 300) 149 | 150 | # Save data and mappings in "p" to reuse them later. 151 | p <- ggplot(small_dbh, aes(dbh)) 152 | ``` 153 | 154 | ```{r} 155 | p + geom_histogram(binwidth = 10) 156 | ``` 157 | 158 | ```{r} 159 | p + geom_histogram(aes(dbh), binwidth = 30) 160 | ``` 161 | 162 | ```{r} 163 | p + geom_histogram(aes(dbh), binwidth = 60) 164 | ``` 165 | 166 | A binwidth of 30 seems useful. 167 | 168 | ```{r} 169 | # Save to reuse 170 | useful_binwidth <- 30 171 | ``` 172 | 173 | To overlay multiple histograms in the same plot, `geom_freqpoly()` may produce clearer plots than `geom_histogram()`, because it is easier to understand overlying lines than bars. 174 | 175 | ```{r} 176 | # Make n groups with ~ numbers of observations with `ggplot2::cut_number()` 177 | small_cut_number <- mutate(small_dbh, equal_n = cut_number(dbh, n = 5)) 178 | 179 | p <- ggplot(data = small_cut_number, aes(x = dbh, color = equal_n)) 180 | 181 | p + geom_histogram() 182 | ``` 183 | 184 | ```{r} 185 | p + geom_freqpoly() 186 | ``` 187 | 188 | ### Typical and rare values 189 | 190 | In both bar charts and histograms, tall and short bars let us explore common and less-common values. For example, we could ask: 191 | 192 | * Which values are the most common? Why? 193 | * Which values are rare? Why? Does that match your expectations? 194 | * Can you see any unusual patterns? What might explain them? 195 | 196 | The latter two plots give a good estimate of the most common stem-diameters. You can compute the same count manually by cutting the variable `dbh` with `ggplot2::cut_width()`, and then counting the unique pieces with `dplyr::count()`. 197 | 198 | ```{r} 199 | small_dbh %>% 200 | mutate(dbh_mm = cut_width(dbh, width = useful_binwidth)) %>% 201 | count(dbh_mm, sort = TRUE) 202 | ``` 203 | 204 | The most common stems have a diameter at breast height (`dbh`) between 15 mm and 45 mm. 205 | 206 | ### Clustered values 207 | 208 | In this section we will focus on the largest stems; later we will explore all stems. 209 | 210 | ```{r} 211 | large_dbh <- stem %>% filter(dbh > 300) 212 | ``` 213 | 214 | Clusters of similar values suggest that subgroups exist in your data. To understand the subgroups, ask: 215 | 216 | * How are the observations within each cluster similar to each other? 217 | * How are the observations in separate clusters different from each other? 218 | * How can you explain or describe the clusters? 219 | * Why might the appearance of clusters be misleading? 220 | 221 | The clustering, however, may be an artifact of the chosen binwidth: 222 | 223 | ```{r, fig.align="default", out.width="45%", fig.widh=(6 * 0.5 / 0.7)} 224 | p <- ggplot(large_dbh, aes(dbh)) 225 | 226 | # Left: Are these clusters meaningful? 227 | p + geom_histogram(binwidth = 25) 228 | 229 | # Right: Is this a more meaningful representation? 230 | p + geom_histogram(binwidth = 100) 231 | ``` 232 | 233 | ### Unusual values 234 | 235 | In this section we will work with the entire `stem` dataset. 236 | 237 | Outliers are observations that are unusual: data points that do not seem to fit the pattern. Sometimes outliers are data entry errors, while other times outliers suggest important new science. When you have a lot of data, outliers can be difficult to see in a histogram. 238 | 239 | For example, consider the distribution of the `dbh` variable of the `stem` dataset. Notice how wide are the limits of the x-axis. 240 | 241 | ```{r} 242 | p <- ggplot(stem, aes(dbh)) + 243 | geom_histogram(binwidth = useful_binwidth) 244 | p 245 | ``` 246 | 247 | There are so many observations in the common bins that the rare bins are so short that you can barely see them. To make the unusual values more noticeable, we can zoom into smaller values of the y-axis with `coord_cartesian()`. 248 | 249 | ```{r} 250 | p + coord_cartesian(ylim = c(0, 15)) 251 | ``` 252 | 253 | `coord_cartesian()` also has an `xlim` argument for when you need to zoom into the x-axis. __ggplot2__ also has `xlim()` and `ylim()` functions that work slightly differently: they throw away the data outside the limits. 254 | 255 | This allows us to see that `dbh` values over ~625 are unusual and may be outliers. We can pluck them out with `dplyr::filter()` and select a subset of informative variables: 256 | 257 | ```{r} 258 | treshold <- 625 259 | unusual <- stem %>% 260 | filter(dbh > treshold ) %>% 261 | select(stemID, ExactDate, status, gx, gy, dbh) %>% 262 | arrange(dbh) 263 | unusual 264 | ``` 265 | 266 | You could plot the unusual stems to see where they are located. 267 | 268 | ```{r} 269 | ggplot(stem, aes(gx, gy)) + 270 | # `alpha` controls opacity 271 | geom_point(alpha = 1/10) + 272 | # highlight unusual stems 273 | geom_point(data = unusual, colour = "red", size = 3) 274 | ``` 275 | 276 | It is good practice to repeat your analysis with and without the outliers. If they have minimal effect on the results, and you can not figure out why they are there, it is reasonable to replace them with missing values, and move on. However, if they have a substantial effect on your results, you should not drop them without justification. You will need to figure out what caused them (e.g. a data entry error) and disclose that you removed them in your write-up. 277 | 278 | # Missing values 279 | 280 | If you have encountered unusual values in your dataset and simply want to move on to the rest of your analysis, you have two options. 281 | 282 | 1. Drop the entire row with the strange values: 283 | 284 | ```{r} 285 | are_usual <- !stem$stemID %in% unusual$stemID 286 | usual <- filter(stem, are_usual) 287 | 288 | # Confirm dataset of usual stems has less rows than full dataset. 289 | nrow(stem) 290 | nrow(usual) 291 | ``` 292 | 293 | I do not recommend this option: That one measurement is invalid does not mean all the measurements are invalid. Additionally, if you have low quality data, by the time you have applied this approach to every variable you might find that you are left with no data! 294 | 295 | 2. Instead, I recommend replacing the unusual values with missing values. The easiest way to do this is to use `dplyr::mutate()` to replace the variable with a modified copy. You can use the `ifelse()` function to replace unusual values with `NA`: 296 | 297 | ```{r} 298 | are_unusual <- !are_usual 299 | with_unusual_made_NA <- stem %>% 300 | mutate(dbh = ifelse(are_unusual, NA_real_, dbh)) 301 | ``` 302 | 303 | `ifelse()` has three arguments. The first argument `test` should be a logical vector. The result will contain the value of the second argument, `yes`, when `test` is `TRUE`, and the value of the third argument, `no`, when it is `FALSE`. 304 | 305 | ```{r} 306 | # Confirm no rows have been removed, 307 | nrow(stem) 308 | nrow(with_unusual_made_NA) 309 | 310 | # but dbh of unusual stems is NA 311 | unusual_only <- with_unusual_made_NA %>% 312 | filter(are_unusual) %>% 313 | select(dbh, stemID) 314 | unusual_only 315 | ``` 316 | 317 | Alternatively to `ifelse()`, use `dplyr::case_when()`. `case_when()` is particularly useful inside `mutate()` when you want to create a new variable that relies on a complex combination of existing variables. 318 | 319 | It is not obvious where you should plot missing values in a plot, so __ggplot2__ does not include them, but it does warn that they have been removed (left plot below). To suppress that warning, set `na.rm = TRUE` (right plot below). 320 | 321 | ```{r, fig.align="default", out.width="45%", fig.widh=(6 * 0.5 / 0.95)} 322 | # Left: Keep NAs and get a warning on the console 323 | ggplot(unusual_only, aes(dbh)) + 324 | geom_histogram(binwidth = useful_binwidth) + 325 | labs(title = "Expect empty plot but get a warning") 326 | 327 | # Right: Remove NAs explicitely in geom_histogram(), so no warning 328 | ggplot(unusual_only, aes(dbh)) + 329 | geom_histogram(binwidth = useful_binwidth, na.rm = TRUE) + 330 | labs(title = "Expect empty plot but no warning") 331 | ``` 332 | 333 | Other times, you may want to understand what makes observations with missing values different to observations with recorded values. 334 | 335 | For example, you might want to compare the `status` for stems with missing and non-missing values of `dbh`. You can do this by making a new variable with `is.na()`. 336 | 337 | ```{r} 338 | missing_dbh <- stem %>% 339 | mutate(missing = is.na(dbh)) 340 | 341 | ggplot(missing_dbh) + 342 | geom_bar(aes(status, fill = missing)) 343 | ``` 344 | 345 | ## Exercises 346 | 347 | 1. What happens to missing values in a histogram? What happens to missing values in a bar chart? Why is there a difference? 348 | 349 | 2. What does `na.rm = TRUE` do in `mean()` and `sum()`? 350 | 351 | # Covariation 352 | 353 | If variation describes the behavior within a variable, covariation describes the behavior between variables. Covariation is the tendency for the values of two or more variables to vary together in a related way. The best way to spot covariation is to visualize the relationship between two or more variables. How you do that should again depend on the type of variables involved. 354 | 355 | ## A categorical and continuous variable 356 | 357 | It is common to explore the distribution of a continuous variable broken down by a categorical variable. The default appearance of `geom_freqpoly()` is not that useful for that sort of comparison since the height is given by the count. That means if one of the groups is much smaller than the others, it is hard to see the differences in shape. For example, let's explore how stem diameter (`dbh`) varies with species (`sp`): 358 | 359 | ```{r} 360 | # The dataset has too many species; choosing just a few for clarity 361 | few_sp <- unique(stem$sp)[1:5] 362 | data_few_sp <- filter(stem, sp %in% few_sp) 363 | 364 | ggplot(data_few_sp, aes(dbh)) + 365 | geom_freqpoly(aes(color = sp)) 366 | ``` 367 | 368 | It is hard to see the difference in distribution, because the overall counts differ so much: 369 | 370 | ```{r} 371 | ggplot(data_few_sp) + 372 | # ordering `sp` from high to low frequency with forcats::fct_infreq() 373 | geom_bar(mapping = aes(x = fct_infreq(sp))) 374 | ``` 375 | 376 | To make the comparison easier, we need to swap what is displayed on the y-axis. Instead of displaying count, we will display density, which is the count standardized so that the area under each frequency polygon is one. 377 | 378 | ```{r} 379 | ggplot(data_few_sp, aes(x= dbh, y = ..density..)) + 380 | geom_freqpoly(aes(color = sp)) 381 | ``` 382 | 383 | Another alternative to display the distribution of a continuous variable broken down by a categorical variable is the boxplot. A boxplot is a type of visual shorthand for a distribution of values that is popular among statisticians. Each boxplot consists of: 384 | 385 | * A box that stretches from the 25th percentile of the distribution to the 75th percentile, a distance known as the interquartile range (IQR). In the middle of the box is a line that displays the median, i.e. 50th percentile, of the distribution. These three lines give you a sense of the spread of the distribution and whether or not the distribution is symmetric about the median or skewed to one side. 386 | 387 | * Visual points that display observations that fall more than 1.5 times the IQR from either edge of the box. These outlying points are unusual so are plotted individually. 388 | 389 | * A line (or whisker) that extends from each end of the box and goes to the 390 | farthest non-outlier point in the distribution. 391 | 392 | 393 | 394 | Let's take a look at the distribution of stem diameter (`dbh`) by species (`sp`) using `geom_boxplot()`: 395 | 396 | ```{r} 397 | ggplot(data_few_sp, aes(sp, dbh)) + 398 | geom_boxplot() 399 | ``` 400 | 401 | We see much less information about the distribution, but the boxplots are much more compact so we can more easily compare them (and fit more on one plot). 402 | 403 | Above we ordered the variable `sp` by its frequency. Now, to make the trend easier to see, we can reorder `sp` based on the median value of `dbh`. One way to do that is with `reorder()`. 404 | 405 | ```{r} 406 | data_few_sp <- data_few_sp %>% 407 | mutate(sp = reorder(sp, dbh, FUN = median, na.rm = TRUE)) 408 | 409 | ggplot(data_few_sp, aes(sp, dbh)) + 410 | geom_boxplot() 411 | ``` 412 | 413 | If you have long variable names, `geom_boxplot()` will work better if you flip it 90°. You can do that with `coord_flip()` (left plot below), or with `ggstance::geom_boxploth()` and swapping `x` and `y` mappings (right plot below): 414 | 415 | ```{r, fig.align="default", out.width="45%", fig.widh=(6 * 0.5 / 0.95)} 416 | # Remember to install with install.packages("ggstance") 417 | library(ggstance) 418 | 419 | # Left 420 | ggplot2::last_plot() + 421 | coord_flip() 422 | 423 | # Right 424 | ggplot(data_few_sp) + 425 | ggstance::geom_boxploth(aes(x = dbh, y = sp)) # swap x, y; compare to above 426 | ``` 427 | 428 | ### Alternatives 429 | 430 | One problem with boxplots is that they were developed in an era of much smaller datasets and tend to display a prohibitively large number of “outlying values”. One approach to remedy this problem is the letter-value plot. 431 | 432 | ```{r} 433 | # Remember to install with install.packages("lvplot") 434 | library(lvplot) 435 | 436 | ggplot(data_few_sp, aes(sp, dbh)) + 437 | lvplot::geom_lv() 438 | ``` 439 | 440 | Compare and contrast `geom_violin()` with a faceted `geom_histogram()`, or a colored `geom_freqpoly()` (). What are the pros and cons of each method? 441 | 442 | ```{r} 443 | ggplot(data_few_sp, aes(sp, dbh)) + 444 | geom_violin() 445 | ``` 446 | 447 | ```{r} 448 | ggplot(data_few_sp, aes(dbh)) + 449 | geom_histogram() + 450 | facet_wrap(~sp) 451 | ``` 452 | 453 | If you have a small dataset, it is sometimes useful to use `geom_jitter()` to see the relationship between a continuous and categorical variable. The __ggbeeswarm__ package provides a number of methods similar to `geom_jitter()`. 454 | 455 | ```{r} 456 | # Remember to install with install.packages("ggbeeswarm") 457 | library(ggbeeswarm) 458 | 459 | small_dataset <- data_few_sp %>% 460 | group_by(sp) %>% 461 | sample_n(50) 462 | 463 | p <- ggplot(small_dataset, aes(sp, dbh)) 464 | 465 | p + geom_point() 466 | ``` 467 | 468 | ```{r} 469 | p + geom_jitter() 470 | ``` 471 | 472 | ```{r} 473 | p + ggbeeswarm::geom_quasirandom() 474 | ``` 475 | 476 | ## Two categorical variables 477 | 478 | To visualize the covariation between categorical variables, you will need to count the number of observations for each combination. One way to do that is to rely on the built-in `geom_count()`. The size of each circle in the plot displays how many observations occurred at each combination of values (left plot below). Covariation will appear as a strong correlation between specific x values and specific y values. 479 | 480 | ```{r} 481 | # Simple count 482 | ggplot(data_few_sp) + 483 | geom_count(aes(x = sp, y = status)) 484 | ``` 485 | 486 | To show the distribution of `status` within `sp` (or `sp` within `status`) more clearly, you can map bubble size to a proportion calculated over `sp` (or over `status`): 487 | 488 | ```{r} 489 | # Proportion; columns sum to 1. 490 | ggplot(data_few_sp, aes(x = sp, y = status)) + 491 | geom_count(aes(size = ..prop.., group = sp)) + 492 | scale_size_area(max_size = 10) 493 | ``` 494 | 495 | ```{r} 496 | few_spp_n <- data_few_sp %>% 497 | count(sp, status) 498 | 499 | few_spp_n 500 | ``` 501 | 502 | Then, visualize with `geom_tile()` and the fill aesthetic: 503 | 504 | ```{r} 505 | ggplot(few_spp_n, aes(sp, status)) + 506 | geom_tile(aes(fill = n)) 507 | ``` 508 | 509 | ## Two continuous variables 510 | 511 | You have already seen one great way to visualize the covariation between two continuous variables: draw a scatterplot with `geom_point()`. You can see covariation as a pattern in the points. For example, we can estimate the basal area of each stem as a function of `dbh` with the equation `ba = 1 / 4 * pi * (dbh)^2`. I will add some error to make the pattern a little more interesting. 512 | 513 | ```{r} 514 | error <- rnorm(length(stem$dbh)) 515 | stem <- stem %>% 516 | mutate(ba = (1 / 4 * (dbh)^2) + error) 517 | 518 | p <- ggplot(stem, aes(dbh, ba)) 519 | p + geom_point() 520 | ``` 521 | 522 | Scatterplots become less useful as the size of your dataset grows, because points begin to overplot and pile up into areas of uniform black (as above). You have already seen one way to fix the problem: using the `alpha` aesthetic to add transparency. 523 | 524 | ```{r} 525 | p + geom_point(alpha = 1 / 25) 526 | ``` 527 | 528 | But using transparency can be challenging for very large datasets. Another solution is to use `bin`. Previously, you used `geom_histogram()` and `geom_freqpoly()` to bin in one dimension. Now, you will learn how to use `geom_bin2d()` and `geom_hex()` to bin in two dimensions. 529 | 530 | `geom_bin2d()` and `geom_hex()` divide the coordinate plane into 2d bins and then use a fill color to display how many points fall into each bin. `geom_bin2d()` creates rectangular bins. `geom_hex()` creates hexagonal bins. You will need to install the __hexbin__ package to use `geom_hex()`. 531 | 532 | ```{r} 533 | # Remember to install with install.packages("hexbin") 534 | # Left 535 | p + geom_bin2d() 536 | 537 | # Right 538 | p + geom_hex() 539 | ``` 540 | 541 | Another option is to bin one continuous variable so it acts like a categorical variable. Then, you can use one of the techniques for visualizing the combination of a categorical and a continuous variable that you learned about. For example, you can bin `dbh` and then display a boxplot for each group: 542 | 543 | ```{r} 544 | p <- ggplot(stem, aes(dbh, ba)) 545 | p + geom_boxplot(aes(group = cut_width(dbh, useful_binwidth))) 546 | ``` 547 | 548 | `cut_width(x, width)`, as used above, divides x into bins of width `width`. By default, boxplots look roughly the same (apart from number of outliers) regardless of how many observations there are; therefore, it is difficult to tell that each boxplot summarizes a different number of points. One way to show that is to make the width of the boxplot proportional to the number of points with `varwidth = TRUE`. 549 | 550 | Another approach is to display approximately the same number of points in each bin. That is the job of `cut_number()`: 551 | 552 | ```{r} 553 | p + geom_boxplot(aes(group = cut_number(dbh, 20))) 554 | ``` 555 | 556 | ## Patterns and models 557 | 558 | Patterns in your data provide clues about relationships. If a systematic relationship exists between two variables, it will appear as a pattern in the data. If you spot a pattern, ask yourself: 559 | 560 | * Could this pattern be due to coincidence (i.e. random chance)? 561 | * How can you describe the relationship implied by the pattern? 562 | * How strong is the relationship implied by the pattern? 563 | * What other variables might affect the relationship? 564 | * Does the relationship change if you look at individual subgroups of the data? 565 | 566 | Above, we learned that a scatterplot of stem diameter (`dbh`) versus basal area (`ba`) shows a pattern: larger stem diameters are associated with larger basal area. 567 | 568 | Patterns provide one of the most useful tools for data scientists, because they reveal covariation. If you think of variation as a phenomenon that creates uncertainty, covariation is a phenomenon that reduces it. If two variables co-vary, you can use the values of one variable to make better predictions about the values of the second. If the covariation is due to a causal relationship (a special case), then you can use the value of one variable to control the value of the second. 569 | 570 | Models are a tool for extracting patterns out of data. For example, consider the `stem` data; `dbh` and `ba` are tightly related. It is possible to use a model to remove the very strong relationship between `dbh` and `ba` so we can explore the subtleties that remain. The following code fits a model that predicts `ba` from `dbh` and then computes the residuals (the difference between the predicted value and the actual value). The residuals give us a view of the basal area of a stem, once the effect of `dbh` has been removed. 571 | 572 | ```{r} 573 | library(modelr) 574 | 575 | mod <- lm(log(ba) ~ log(dbh), data = stem) 576 | resid_added <- stem %>% 577 | add_residuals(mod) %>% 578 | mutate(resid = exp(resid)) 579 | 580 | ggplot(data = resid_added, aes(x = dbh, y = resid)) + 581 | geom_point() 582 | ``` 583 | 584 | There is no pattern left. This is not surprising since we created `ba` as a precise function of `dbh` plus a random error -- once we removed the pattern due to `dbh`, all that remains is noise. 585 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU General Public License 2 | ========================== 3 | 4 | _Version 3, 29 June 2007_ 5 | _Copyright © 2007 Free Software Foundation, Inc. <>_ 6 | 7 | Everyone is permitted to copy and distribute verbatim copies of this license 8 | document, but changing it is not allowed. 9 | 10 | ## Preamble 11 | 12 | The GNU General Public License is a free, copyleft license for software and other 13 | kinds of works. 14 | 15 | The licenses for most software and other practical works are designed to take away 16 | your freedom to share and change the works. By contrast, the GNU General Public 17 | License is intended to guarantee your freedom to share and change all versions of a 18 | program--to make sure it remains free software for all its users. We, the Free 19 | Software Foundation, use the GNU General Public License for most of our software; it 20 | applies also to any other work released this way by its authors. You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not price. Our General 24 | Public Licenses are designed to make sure that you have the freedom to distribute 25 | copies of free software (and charge for them if you wish), that you receive source 26 | code or can get it if you want it, that you can change the software or use pieces of 27 | it in new free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you these rights or 30 | asking you to surrender the rights. Therefore, you have certain responsibilities if 31 | you distribute copies of the software, or if you modify it: responsibilities to 32 | respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether gratis or for a fee, 35 | you must pass on to the recipients the same freedoms that you received. You must make 36 | sure that they, too, receive or can get the source code. And you must show them these 37 | terms so they know their rights. 38 | 39 | Developers that use the GNU GPL protect your rights with two steps: **(1)** assert 40 | copyright on the software, and **(2)** offer you this License giving you legal permission 41 | to copy, distribute and/or modify it. 42 | 43 | For the developers' and authors' protection, the GPL clearly explains that there is 44 | no warranty for this free software. For both users' and authors' sake, the GPL 45 | requires that modified versions be marked as changed, so that their problems will not 46 | be attributed erroneously to authors of previous versions. 47 | 48 | Some devices are designed to deny users access to install or run modified versions of 49 | the software inside them, although the manufacturer can do so. This is fundamentally 50 | incompatible with the aim of protecting users' freedom to change the software. The 51 | systematic pattern of such abuse occurs in the area of products for individuals to 52 | use, which is precisely where it is most unacceptable. Therefore, we have designed 53 | this version of the GPL to prohibit the practice for those products. If such problems 54 | arise substantially in other domains, we stand ready to extend this provision to 55 | those domains in future versions of the GPL, as needed to protect the freedom of 56 | users. 57 | 58 | Finally, every program is threatened constantly by software patents. States should 59 | not allow patents to restrict development and use of software on general-purpose 60 | computers, but in those that do, we wish to avoid the special danger that patents 61 | applied to a free program could make it effectively proprietary. To prevent this, the 62 | GPL assures that patents cannot be used to render the program non-free. 63 | 64 | The precise terms and conditions for copying, distribution and modification follow. 65 | 66 | ## TERMS AND CONDITIONS 67 | 68 | ### 0. Definitions 69 | 70 | “This License” refers to version 3 of the GNU General Public License. 71 | 72 | “Copyright” also means copyright-like laws that apply to other kinds of 73 | works, such as semiconductor masks. 74 | 75 | “The Program” refers to any copyrightable work licensed under this 76 | License. Each licensee is addressed as “you”. “Licensees” and 77 | “recipients” may be individuals or organizations. 78 | 79 | To “modify” a work means to copy from or adapt all or part of the work in 80 | a fashion requiring copyright permission, other than the making of an exact copy. The 81 | resulting work is called a “modified version” of the earlier work or a 82 | work “based on” the earlier work. 83 | 84 | A “covered work” means either the unmodified Program or a work based on 85 | the Program. 86 | 87 | To “propagate” a work means to do anything with it that, without 88 | permission, would make you directly or secondarily liable for infringement under 89 | applicable copyright law, except executing it on a computer or modifying a private 90 | copy. Propagation includes copying, distribution (with or without modification), 91 | making available to the public, and in some countries other activities as well. 92 | 93 | To “convey” a work means any kind of propagation that enables other 94 | parties to make or receive copies. Mere interaction with a user through a computer 95 | network, with no transfer of a copy, is not conveying. 96 | 97 | An interactive user interface displays “Appropriate Legal Notices” to the 98 | extent that it includes a convenient and prominently visible feature that **(1)** 99 | displays an appropriate copyright notice, and **(2)** tells the user that there is no 100 | warranty for the work (except to the extent that warranties are provided), that 101 | licensees may convey the work under this License, and how to view a copy of this 102 | License. If the interface presents a list of user commands or options, such as a 103 | menu, a prominent item in the list meets this criterion. 104 | 105 | ### 1. Source Code 106 | 107 | The “source code” for a work means the preferred form of the work for 108 | making modifications to it. “Object code” means any non-source form of a 109 | work. 110 | 111 | A “Standard Interface” means an interface that either is an official 112 | standard defined by a recognized standards body, or, in the case of interfaces 113 | specified for a particular programming language, one that is widely used among 114 | developers working in that language. 115 | 116 | The “System Libraries” of an executable work include anything, other than 117 | the work as a whole, that **(a)** is included in the normal form of packaging a Major 118 | Component, but which is not part of that Major Component, and **(b)** serves only to 119 | enable use of the work with that Major Component, or to implement a Standard 120 | Interface for which an implementation is available to the public in source code form. 121 | A “Major Component”, in this context, means a major essential component 122 | (kernel, window system, and so on) of the specific operating system (if any) on which 123 | the executable work runs, or a compiler used to produce the work, or an object code 124 | interpreter used to run it. 125 | 126 | The “Corresponding Source” for a work in object code form means all the 127 | source code needed to generate, install, and (for an executable work) run the object 128 | code and to modify the work, including scripts to control those activities. However, 129 | it does not include the work's System Libraries, or general-purpose tools or 130 | generally available free programs which are used unmodified in performing those 131 | activities but which are not part of the work. For example, Corresponding Source 132 | includes interface definition files associated with source files for the work, and 133 | the source code for shared libraries and dynamically linked subprograms that the work 134 | is specifically designed to require, such as by intimate data communication or 135 | control flow between those subprograms and other parts of the work. 136 | 137 | The Corresponding Source need not include anything that users can regenerate 138 | automatically from other parts of the Corresponding Source. 139 | 140 | The Corresponding Source for a work in source code form is that same work. 141 | 142 | ### 2. Basic Permissions 143 | 144 | All rights granted under this License are granted for the term of copyright on the 145 | Program, and are irrevocable provided the stated conditions are met. This License 146 | explicitly affirms your unlimited permission to run the unmodified Program. The 147 | output from running a covered work is covered by this License only if the output, 148 | given its content, constitutes a covered work. This License acknowledges your rights 149 | of fair use or other equivalent, as provided by copyright law. 150 | 151 | You may make, run and propagate covered works that you do not convey, without 152 | conditions so long as your license otherwise remains in force. You may convey covered 153 | works to others for the sole purpose of having them make modifications exclusively 154 | for you, or provide you with facilities for running those works, provided that you 155 | comply with the terms of this License in conveying all material for which you do not 156 | control copyright. Those thus making or running the covered works for you must do so 157 | exclusively on your behalf, under your direction and control, on terms that prohibit 158 | them from making any copies of your copyrighted material outside their relationship 159 | with you. 160 | 161 | Conveying under any other circumstances is permitted solely under the conditions 162 | stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 163 | 164 | ### 3. Protecting Users' Legal Rights From Anti-Circumvention Law 165 | 166 | No covered work shall be deemed part of an effective technological measure under any 167 | applicable law fulfilling obligations under article 11 of the WIPO copyright treaty 168 | adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention 169 | of such measures. 170 | 171 | When you convey a covered work, you waive any legal power to forbid circumvention of 172 | technological measures to the extent such circumvention is effected by exercising 173 | rights under this License with respect to the covered work, and you disclaim any 174 | intention to limit operation or modification of the work as a means of enforcing, 175 | against the work's users, your or third parties' legal rights to forbid circumvention 176 | of technological measures. 177 | 178 | ### 4. Conveying Verbatim Copies 179 | 180 | You may convey verbatim copies of the Program's source code as you receive it, in any 181 | medium, provided that you conspicuously and appropriately publish on each copy an 182 | appropriate copyright notice; keep intact all notices stating that this License and 183 | any non-permissive terms added in accord with section 7 apply to the code; keep 184 | intact all notices of the absence of any warranty; and give all recipients a copy of 185 | this License along with the Program. 186 | 187 | You may charge any price or no price for each copy that you convey, and you may offer 188 | support or warranty protection for a fee. 189 | 190 | ### 5. Conveying Modified Source Versions 191 | 192 | You may convey a work based on the Program, or the modifications to produce it from 193 | the Program, in the form of source code under the terms of section 4, provided that 194 | you also meet all of these conditions: 195 | 196 | * **a)** The work must carry prominent notices stating that you modified it, and giving a 197 | relevant date. 198 | * **b)** The work must carry prominent notices stating that it is released under this 199 | License and any conditions added under section 7. This requirement modifies the 200 | requirement in section 4 to “keep intact all notices”. 201 | * **c)** You must license the entire work, as a whole, under this License to anyone who 202 | comes into possession of a copy. This License will therefore apply, along with any 203 | applicable section 7 additional terms, to the whole of the work, and all its parts, 204 | regardless of how they are packaged. This License gives no permission to license the 205 | work in any other way, but it does not invalidate such permission if you have 206 | separately received it. 207 | * **d)** If the work has interactive user interfaces, each must display Appropriate Legal 208 | Notices; however, if the Program has interactive interfaces that do not display 209 | Appropriate Legal Notices, your work need not make them do so. 210 | 211 | A compilation of a covered work with other separate and independent works, which are 212 | not by their nature extensions of the covered work, and which are not combined with 213 | it such as to form a larger program, in or on a volume of a storage or distribution 214 | medium, is called an “aggregate” if the compilation and its resulting 215 | copyright are not used to limit the access or legal rights of the compilation's users 216 | beyond what the individual works permit. Inclusion of a covered work in an aggregate 217 | does not cause this License to apply to the other parts of the aggregate. 218 | 219 | ### 6. Conveying Non-Source Forms 220 | 221 | You may convey a covered work in object code form under the terms of sections 4 and 222 | 5, provided that you also convey the machine-readable Corresponding Source under the 223 | terms of this License, in one of these ways: 224 | 225 | * **a)** Convey the object code in, or embodied in, a physical product (including a 226 | physical distribution medium), accompanied by the Corresponding Source fixed on a 227 | durable physical medium customarily used for software interchange. 228 | * **b)** Convey the object code in, or embodied in, a physical product (including a 229 | physical distribution medium), accompanied by a written offer, valid for at least 230 | three years and valid for as long as you offer spare parts or customer support for 231 | that product model, to give anyone who possesses the object code either **(1)** a copy of 232 | the Corresponding Source for all the software in the product that is covered by this 233 | License, on a durable physical medium customarily used for software interchange, for 234 | a price no more than your reasonable cost of physically performing this conveying of 235 | source, or **(2)** access to copy the Corresponding Source from a network server at no 236 | charge. 237 | * **c)** Convey individual copies of the object code with a copy of the written offer to 238 | provide the Corresponding Source. This alternative is allowed only occasionally and 239 | noncommercially, and only if you received the object code with such an offer, in 240 | accord with subsection 6b. 241 | * **d)** Convey the object code by offering access from a designated place (gratis or for 242 | a charge), and offer equivalent access to the Corresponding Source in the same way 243 | through the same place at no further charge. You need not require recipients to copy 244 | the Corresponding Source along with the object code. If the place to copy the object 245 | code is a network server, the Corresponding Source may be on a different server 246 | (operated by you or a third party) that supports equivalent copying facilities, 247 | provided you maintain clear directions next to the object code saying where to find 248 | the Corresponding Source. Regardless of what server hosts the Corresponding Source, 249 | you remain obligated to ensure that it is available for as long as needed to satisfy 250 | these requirements. 251 | * **e)** Convey the object code using peer-to-peer transmission, provided you inform 252 | other peers where the object code and Corresponding Source of the work are being 253 | offered to the general public at no charge under subsection 6d. 254 | 255 | A separable portion of the object code, whose source code is excluded from the 256 | Corresponding Source as a System Library, need not be included in conveying the 257 | object code work. 258 | 259 | A “User Product” is either **(1)** a “consumer product”, which 260 | means any tangible personal property which is normally used for personal, family, or 261 | household purposes, or **(2)** anything designed or sold for incorporation into a 262 | dwelling. In determining whether a product is a consumer product, doubtful cases 263 | shall be resolved in favor of coverage. For a particular product received by a 264 | particular user, “normally used” refers to a typical or common use of 265 | that class of product, regardless of the status of the particular user or of the way 266 | in which the particular user actually uses, or expects or is expected to use, the 267 | product. A product is a consumer product regardless of whether the product has 268 | substantial commercial, industrial or non-consumer uses, unless such uses represent 269 | the only significant mode of use of the product. 270 | 271 | “Installation Information” for a User Product means any methods, 272 | procedures, authorization keys, or other information required to install and execute 273 | modified versions of a covered work in that User Product from a modified version of 274 | its Corresponding Source. The information must suffice to ensure that the continued 275 | functioning of the modified object code is in no case prevented or interfered with 276 | solely because modification has been made. 277 | 278 | If you convey an object code work under this section in, or with, or specifically for 279 | use in, a User Product, and the conveying occurs as part of a transaction in which 280 | the right of possession and use of the User Product is transferred to the recipient 281 | in perpetuity or for a fixed term (regardless of how the transaction is 282 | characterized), the Corresponding Source conveyed under this section must be 283 | accompanied by the Installation Information. But this requirement does not apply if 284 | neither you nor any third party retains the ability to install modified object code 285 | on the User Product (for example, the work has been installed in ROM). 286 | 287 | The requirement to provide Installation Information does not include a requirement to 288 | continue to provide support service, warranty, or updates for a work that has been 289 | modified or installed by the recipient, or for the User Product in which it has been 290 | modified or installed. Access to a network may be denied when the modification itself 291 | materially and adversely affects the operation of the network or violates the rules 292 | and protocols for communication across the network. 293 | 294 | Corresponding Source conveyed, and Installation Information provided, in accord with 295 | this section must be in a format that is publicly documented (and with an 296 | implementation available to the public in source code form), and must require no 297 | special password or key for unpacking, reading or copying. 298 | 299 | ### 7. Additional Terms 300 | 301 | “Additional permissions” are terms that supplement the terms of this 302 | License by making exceptions from one or more of its conditions. Additional 303 | permissions that are applicable to the entire Program shall be treated as though they 304 | were included in this License, to the extent that they are valid under applicable 305 | law. If additional permissions apply only to part of the Program, that part may be 306 | used separately under those permissions, but the entire Program remains governed by 307 | this License without regard to the additional permissions. 308 | 309 | When you convey a copy of a covered work, you may at your option remove any 310 | additional permissions from that copy, or from any part of it. (Additional 311 | permissions may be written to require their own removal in certain cases when you 312 | modify the work.) You may place additional permissions on material, added by you to a 313 | covered work, for which you have or can give appropriate copyright permission. 314 | 315 | Notwithstanding any other provision of this License, for material you add to a 316 | covered work, you may (if authorized by the copyright holders of that material) 317 | supplement the terms of this License with terms: 318 | 319 | * **a)** Disclaiming warranty or limiting liability differently from the terms of 320 | sections 15 and 16 of this License; or 321 | * **b)** Requiring preservation of specified reasonable legal notices or author 322 | attributions in that material or in the Appropriate Legal Notices displayed by works 323 | containing it; or 324 | * **c)** Prohibiting misrepresentation of the origin of that material, or requiring that 325 | modified versions of such material be marked in reasonable ways as different from the 326 | original version; or 327 | * **d)** Limiting the use for publicity purposes of names of licensors or authors of the 328 | material; or 329 | * **e)** Declining to grant rights under trademark law for use of some trade names, 330 | trademarks, or service marks; or 331 | * **f)** Requiring indemnification of licensors and authors of that material by anyone 332 | who conveys the material (or modified versions of it) with contractual assumptions of 333 | liability to the recipient, for any liability that these contractual assumptions 334 | directly impose on those licensors and authors. 335 | 336 | All other non-permissive additional terms are considered “further 337 | restrictions” within the meaning of section 10. If the Program as you received 338 | it, or any part of it, contains a notice stating that it is governed by this License 339 | along with a term that is a further restriction, you may remove that term. If a 340 | license document contains a further restriction but permits relicensing or conveying 341 | under this License, you may add to a covered work material governed by the terms of 342 | that license document, provided that the further restriction does not survive such 343 | relicensing or conveying. 344 | 345 | If you add terms to a covered work in accord with this section, you must place, in 346 | the relevant source files, a statement of the additional terms that apply to those 347 | files, or a notice indicating where to find the applicable terms. 348 | 349 | Additional terms, permissive or non-permissive, may be stated in the form of a 350 | separately written license, or stated as exceptions; the above requirements apply 351 | either way. 352 | 353 | ### 8. Termination 354 | 355 | You may not propagate or modify a covered work except as expressly provided under 356 | this License. Any attempt otherwise to propagate or modify it is void, and will 357 | automatically terminate your rights under this License (including any patent licenses 358 | granted under the third paragraph of section 11). 359 | 360 | However, if you cease all violation of this License, then your license from a 361 | particular copyright holder is reinstated **(a)** provisionally, unless and until the 362 | copyright holder explicitly and finally terminates your license, and **(b)** permanently, 363 | if the copyright holder fails to notify you of the violation by some reasonable means 364 | prior to 60 days after the cessation. 365 | 366 | Moreover, your license from a particular copyright holder is reinstated permanently 367 | if the copyright holder notifies you of the violation by some reasonable means, this 368 | is the first time you have received notice of violation of this License (for any 369 | work) from that copyright holder, and you cure the violation prior to 30 days after 370 | your receipt of the notice. 371 | 372 | Termination of your rights under this section does not terminate the licenses of 373 | parties who have received copies or rights from you under this License. If your 374 | rights have been terminated and not permanently reinstated, you do not qualify to 375 | receive new licenses for the same material under section 10. 376 | 377 | ### 9. Acceptance Not Required for Having Copies 378 | 379 | You are not required to accept this License in order to receive or run a copy of the 380 | Program. Ancillary propagation of a covered work occurring solely as a consequence of 381 | using peer-to-peer transmission to receive a copy likewise does not require 382 | acceptance. However, nothing other than this License grants you permission to 383 | propagate or modify any covered work. These actions infringe copyright if you do not 384 | accept this License. Therefore, by modifying or propagating a covered work, you 385 | indicate your acceptance of this License to do so. 386 | 387 | ### 10. Automatic Licensing of Downstream Recipients 388 | 389 | Each time you convey a covered work, the recipient automatically receives a license 390 | from the original licensors, to run, modify and propagate that work, subject to this 391 | License. You are not responsible for enforcing compliance by third parties with this 392 | License. 393 | 394 | An “entity transaction” is a transaction transferring control of an 395 | organization, or substantially all assets of one, or subdividing an organization, or 396 | merging organizations. If propagation of a covered work results from an entity 397 | transaction, each party to that transaction who receives a copy of the work also 398 | receives whatever licenses to the work the party's predecessor in interest had or 399 | could give under the previous paragraph, plus a right to possession of the 400 | Corresponding Source of the work from the predecessor in interest, if the predecessor 401 | has it or can get it with reasonable efforts. 402 | 403 | You may not impose any further restrictions on the exercise of the rights granted or 404 | affirmed under this License. For example, you may not impose a license fee, royalty, 405 | or other charge for exercise of rights granted under this License, and you may not 406 | initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging 407 | that any patent claim is infringed by making, using, selling, offering for sale, or 408 | importing the Program or any portion of it. 409 | 410 | ### 11. Patents 411 | 412 | A “contributor” is a copyright holder who authorizes use under this 413 | License of the Program or a work on which the Program is based. The work thus 414 | licensed is called the contributor's “contributor version”. 415 | 416 | A contributor's “essential patent claims” are all patent claims owned or 417 | controlled by the contributor, whether already acquired or hereafter acquired, that 418 | would be infringed by some manner, permitted by this License, of making, using, or 419 | selling its contributor version, but do not include claims that would be infringed 420 | only as a consequence of further modification of the contributor version. For 421 | purposes of this definition, “control” includes the right to grant patent 422 | sublicenses in a manner consistent with the requirements of this License. 423 | 424 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent license 425 | under the contributor's essential patent claims, to make, use, sell, offer for sale, 426 | import and otherwise run, modify and propagate the contents of its contributor 427 | version. 428 | 429 | In the following three paragraphs, a “patent license” is any express 430 | agreement or commitment, however denominated, not to enforce a patent (such as an 431 | express permission to practice a patent or covenant not to sue for patent 432 | infringement). To “grant” such a patent license to a party means to make 433 | such an agreement or commitment not to enforce a patent against the party. 434 | 435 | If you convey a covered work, knowingly relying on a patent license, and the 436 | Corresponding Source of the work is not available for anyone to copy, free of charge 437 | and under the terms of this License, through a publicly available network server or 438 | other readily accessible means, then you must either **(1)** cause the Corresponding 439 | Source to be so available, or **(2)** arrange to deprive yourself of the benefit of the 440 | patent license for this particular work, or **(3)** arrange, in a manner consistent with 441 | the requirements of this License, to extend the patent license to downstream 442 | recipients. “Knowingly relying” means you have actual knowledge that, but 443 | for the patent license, your conveying the covered work in a country, or your 444 | recipient's use of the covered work in a country, would infringe one or more 445 | identifiable patents in that country that you have reason to believe are valid. 446 | 447 | If, pursuant to or in connection with a single transaction or arrangement, you 448 | convey, or propagate by procuring conveyance of, a covered work, and grant a patent 449 | license to some of the parties receiving the covered work authorizing them to use, 450 | propagate, modify or convey a specific copy of the covered work, then the patent 451 | license you grant is automatically extended to all recipients of the covered work and 452 | works based on it. 453 | 454 | A patent license is “discriminatory” if it does not include within the 455 | scope of its coverage, prohibits the exercise of, or is conditioned on the 456 | non-exercise of one or more of the rights that are specifically granted under this 457 | License. You may not convey a covered work if you are a party to an arrangement with 458 | a third party that is in the business of distributing software, under which you make 459 | payment to the third party based on the extent of your activity of conveying the 460 | work, and under which the third party grants, to any of the parties who would receive 461 | the covered work from you, a discriminatory patent license **(a)** in connection with 462 | copies of the covered work conveyed by you (or copies made from those copies), or **(b)** 463 | primarily for and in connection with specific products or compilations that contain 464 | the covered work, unless you entered into that arrangement, or that patent license 465 | was granted, prior to 28 March 2007. 466 | 467 | Nothing in this License shall be construed as excluding or limiting any implied 468 | license or other defenses to infringement that may otherwise be available to you 469 | under applicable patent law. 470 | 471 | ### 12. No Surrender of Others' Freedom 472 | 473 | If conditions are imposed on you (whether by court order, agreement or otherwise) 474 | that contradict the conditions of this License, they do not excuse you from the 475 | conditions of this License. If you cannot convey a covered work so as to satisfy 476 | simultaneously your obligations under this License and any other pertinent 477 | obligations, then as a consequence you may not convey it at all. For example, if you 478 | agree to terms that obligate you to collect a royalty for further conveying from 479 | those to whom you convey the Program, the only way you could satisfy both those terms 480 | and this License would be to refrain entirely from conveying the Program. 481 | 482 | ### 13. Use with the GNU Affero General Public License 483 | 484 | Notwithstanding any other provision of this License, you have permission to link or 485 | combine any covered work with a work licensed under version 3 of the GNU Affero 486 | General Public License into a single combined work, and to convey the resulting work. 487 | The terms of this License will continue to apply to the part which is the covered 488 | work, but the special requirements of the GNU Affero General Public License, section 489 | 13, concerning interaction through a network will apply to the combination as such. 490 | 491 | ### 14. Revised Versions of this License 492 | 493 | The Free Software Foundation may publish revised and/or new versions of the GNU 494 | General Public License from time to time. Such new versions will be similar in spirit 495 | to the present version, but may differ in detail to address new problems or concerns. 496 | 497 | Each version is given a distinguishing version number. If the Program specifies that 498 | a certain numbered version of the GNU General Public License “or any later 499 | version” applies to it, you have the option of following the terms and 500 | conditions either of that numbered version or of any later version published by the 501 | Free Software Foundation. If the Program does not specify a version number of the GNU 502 | General Public License, you may choose any version ever published by the Free 503 | Software Foundation. 504 | 505 | If the Program specifies that a proxy can decide which future versions of the GNU 506 | General Public License can be used, that proxy's public statement of acceptance of a 507 | version permanently authorizes you to choose that version for the Program. 508 | 509 | Later license versions may give you additional or different permissions. However, no 510 | additional obligations are imposed on any author or copyright holder as a result of 511 | your choosing to follow a later version. 512 | 513 | ### 15. Disclaimer of Warranty 514 | 515 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 516 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 517 | PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER 518 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 519 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE 520 | QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 521 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 522 | 523 | ### 16. Limitation of Liability 524 | 525 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY 526 | COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS 527 | PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, 528 | INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 529 | PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE 530 | OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE 531 | WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 532 | POSSIBILITY OF SUCH DAMAGES. 533 | 534 | ### 17. Interpretation of Sections 15 and 16 535 | 536 | If the disclaimer of warranty and limitation of liability provided above cannot be 537 | given local legal effect according to their terms, reviewing courts shall apply local 538 | law that most closely approximates an absolute waiver of all civil liability in 539 | connection with the Program, unless a warranty or assumption of liability accompanies 540 | a copy of the Program in return for a fee. 541 | 542 | _END OF TERMS AND CONDITIONS_ 543 | 544 | ## How to Apply These Terms to Your New Programs 545 | 546 | If you develop a new program, and you want it to be of the greatest possible use to 547 | the public, the best way to achieve this is to make it free software which everyone 548 | can redistribute and change under these terms. 549 | 550 | To do so, attach the following notices to the program. It is safest to attach them 551 | to the start of each source file to most effectively state the exclusion of warranty; 552 | and each file should have at least the “copyright” line and a pointer to 553 | where the full notice is found. 554 | 555 | 556 | Copyright (C) 2018 Mauro Lepore 557 | 558 | This program is free software: you can redistribute it and/or modify 559 | it under the terms of the GNU General Public License as published by 560 | the Free Software Foundation, either version 3 of the License, or 561 | (at your option) any later version. 562 | 563 | This program is distributed in the hope that it will be useful, 564 | but WITHOUT ANY WARRANTY; without even the implied warranty of 565 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 566 | GNU General Public License for more details. 567 | 568 | You should have received a copy of the GNU General Public License 569 | along with this program. If not, see . 570 | 571 | Also add information on how to contact you by electronic and paper mail. 572 | 573 | If the program does terminal interaction, make it output a short notice like this 574 | when it starts in an interactive mode: 575 | 576 | fgeo Copyright (C) 2018 Mauro Lepore 577 | This program comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. 578 | This is free software, and you are welcome to redistribute it 579 | under certain conditions; type 'show c' for details. 580 | 581 | The hypothetical commands `show w` and `show c` should show the appropriate parts of 582 | the General Public License. Of course, your program's commands might be different; 583 | for a GUI interface, you would use an “about box”. 584 | 585 | You should also get your employer (if you work as a programmer) or school, if any, to 586 | sign a “copyright disclaimer” for the program, if necessary. For more 587 | information on this, and how to apply and follow the GNU GPL, see 588 | <>. 589 | 590 | The GNU General Public License does not permit incorporating your program into 591 | proprietary programs. If your program is a subroutine library, you may consider it 592 | more useful to permit linking proprietary applications with the library. If this is 593 | what you want to do, use the GNU Lesser General Public License instead of this 594 | License. But first, please read 595 | <>. 596 | --------------------------------------------------------------------------------