├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── test-coverage.yaml ├── LICENSE ├── .gitignore ├── data └── abap_visit_vars.rda ├── man ├── figures │ ├── README-unnamed-chunk-4-1.png │ ├── README-unnamed-chunk-5-1.png │ └── README-unnamed-chunk-6-1.png ├── pipe.Rd ├── getCardRecords.Rd ├── findPentadFromCoords.Rd ├── jsonToTibble.Rd ├── searchAbapSpecies.Rd ├── getRegionPentads.Rd ├── abap_visit_vars.Rd ├── addVarEEimage.Rd ├── uploadPentadsToEE.Rd ├── addVarEEclosestImage.Rd ├── EEcollectionToMultiband.Rd ├── getAbapData.Rd ├── addVarEEcollection.Rd ├── abapToUnmarked_multi.Rd ├── abapToUnmarked_single.Rd ├── abapToSpOcc_single.Rd ├── abapToSpOcc_multi.Rd ├── addEEtoSpOcc_single.Rd ├── addEEtoUnmarked_single.Rd ├── addEEtoSpOcc_multi.Rd ├── abapToOccuR.Rd └── addEEtoUnmarked_multi.Rd ├── tests ├── testthat │ ├── fixtures │ │ ├── empty_abap_df_20231003.rds │ │ ├── empty_card_df_20231003.rds │ │ └── empty_pentad_df_20231003.rds │ ├── test-uploadPentadsToEE.R │ ├── test-addVarEEimage.R │ ├── helper.R │ ├── test-addVarEEclosestImage.R │ ├── test-addVarEEcollection.R │ ├── test-getRegionPentads.R │ ├── test-EEcollectionToMultiband.R │ ├── test-getCardRecords.R │ └── test-getAbapData.R └── testthat.R ├── .Rbuildignore ├── codecov.yml ├── data_prep ├── abap_visit_vars.R └── pentads_prep.R ├── R ├── utils-pipe.R ├── jsonToTibble.R ├── getCardRecords.R ├── findPentadFromCoords.R ├── searchAbapSpecies.R ├── abap_visit_vars.R ├── getRegionPentads.R ├── addVarEEimage.R ├── uploadPentadsToEE.R ├── addVarEEclosestImage.R ├── EEcollectionToMultiband.R ├── addVarEEcollection.R ├── getAbapData.R ├── abapToUnmarked_single.R ├── abapToSpOcc_single.R ├── addEEtoSpOcc_single.R ├── abapToUnmarked_multi.R ├── addEEtoUnmarked_single.R ├── abapToSpOcc_multi.R └── abapToOccuR.R ├── ABAP.Rproj ├── NAMESPACE ├── DESCRIPTION ├── LICENSE.md ├── NEWS.md ├── beta ├── abapTo.R └── getAbapData.R ├── CITATION.cff ├── README.md └── README.Rmd /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2021 2 | COPYRIGHT HOLDER: BIRDIE Development Team 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | main_dev.R 6 | beta/* 7 | -------------------------------------------------------------------------------- /data/abap_visit_vars.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/data/abap_visit_vars.rda -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-4-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/man/figures/README-unnamed-chunk-4-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-5-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/man/figures/README-unnamed-chunk-5-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/man/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /tests/testthat/fixtures/empty_abap_df_20231003.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/tests/testthat/fixtures/empty_abap_df_20231003.rds -------------------------------------------------------------------------------- /tests/testthat/fixtures/empty_card_df_20231003.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/tests/testthat/fixtures/empty_card_df_20231003.rds -------------------------------------------------------------------------------- /tests/testthat/fixtures/empty_pentad_df_20231003.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AfricaBirdData/ABAP/HEAD/tests/testthat/fixtures/empty_pentad_df_20231003.rds -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^ABAP\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | main_dev.R 5 | beta/* 6 | ^README\.Rmd$ 7 | data_prep/* 8 | ^CITATION\.cff$ 9 | ^\.github$ 10 | ^codecov\.yml$ 11 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /data_prep/abap_visit_vars.R: -------------------------------------------------------------------------------- 1 | library(ABAP) 2 | 3 | # Load data from a random species 4 | abap_visit_vars <- ABAP::getAbapData(151, "country", "south africa", .years = 2010:2020) 5 | 6 | abap_visit_vars <- abap_visit_vars %>% 7 | dplyr::slice(0) 8 | 9 | # Save data --------------------------------------------------------------- 10 | 11 | # Save as data 12 | usethis::use_data(abap_visit_vars, overwrite = TRUE) 13 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | #' @param lhs A value or the magrittr placeholder. 12 | #' @param rhs A function call using the magrittr semantics. 13 | #' @return The result of calling `rhs(lhs)`. 14 | NULL 15 | -------------------------------------------------------------------------------- /ABAP.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 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 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(ABAP) 11 | 12 | test_check("ABAP") 13 | -------------------------------------------------------------------------------- /data_prep/pentads_prep.R: -------------------------------------------------------------------------------- 1 | library(tidyverse) 2 | library(sf) 3 | 4 | rm(list = ls()) 5 | 6 | # Load pentad data from kml. This was downloaded from the website 7 | pentads_sabap <- sf::st_read("../gis/gis_data/project_sabap2.kml") 8 | 9 | # Remove description because it is empty 10 | pentads_sabap <- dplyr::select(pentads_sabap, Name) 11 | 12 | # Remove Z dimension 13 | pentads_sabap <- sf::st_zm(pentads_sabap) 14 | 15 | # Save as data 16 | usethis::use_data(pentads_sabap, overwrite = TRUE) 17 | 18 | -------------------------------------------------------------------------------- /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 | \arguments{ 10 | \item{lhs}{A value or the magrittr placeholder.} 11 | 12 | \item{rhs}{A function call using the magrittr semantics.} 13 | } 14 | \value{ 15 | The result of calling \code{rhs(lhs)}. 16 | } 17 | \description{ 18 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 19 | } 20 | \keyword{internal} 21 | -------------------------------------------------------------------------------- /man/getCardRecords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getCardRecords.R 3 | \name{getCardRecords} 4 | \alias{getCardRecords} 5 | \title{Download the list of records from an ABAP card} 6 | \usage{ 7 | getCardRecords(.CardNo) 8 | } 9 | \arguments{ 10 | \item{.CardNo}{An ABAP card code} 11 | } 12 | \value{ 13 | A tibble in which each row corresponds to an entry to an ABAP card. 14 | } 15 | \description{ 16 | Download the list of records from an ABAP card 17 | } 18 | \examples{ 19 | getCardRecords("3335_2320_011617_20211219") 20 | } 21 | -------------------------------------------------------------------------------- /tests/testthat/test-uploadPentadsToEE.R: -------------------------------------------------------------------------------- 1 | test_that("returns a deprecation message", { 2 | lifecycle::expect_deprecated(uploadPentadsToEE(pentads = pentads, 3 | asset_id = assetId, 4 | load = TRUE)) 5 | }) 6 | 7 | 8 | test_that("informs about an alternative", { 9 | expect_message(uploadPentadsToEE(pentads = pentads, 10 | asset_id = assetId, 11 | load = TRUE), 12 | regexp = "This function has been discontinued. Please, use ABDtools::uploadFeaturesToEE() instead", 13 | fixed = TRUE) 14 | }) 15 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export(EEcollectionToMultiband) 5 | export(abapToOccuR) 6 | export(abapToSpOcc_multi) 7 | export(abapToSpOcc_single) 8 | export(abapToUnmarked_multi) 9 | export(abapToUnmarked_single) 10 | export(addEEtoSpOcc_multi) 11 | export(addEEtoSpOcc_single) 12 | export(addEEtoUnmarked_multi) 13 | export(addEEtoUnmarked_single) 14 | export(addVarEEclosestImage) 15 | export(addVarEEcollection) 16 | export(addVarEEimage) 17 | export(findPentadFromCoords) 18 | export(getAbapData) 19 | export(getCardRecords) 20 | export(getRegionPentads) 21 | export(jsonToTibble) 22 | export(searchAbapSpecies) 23 | export(uploadPentadsToEE) 24 | importFrom(magrittr,"%>%") 25 | -------------------------------------------------------------------------------- /man/findPentadFromCoords.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/findPentadFromCoords.R 3 | \name{findPentadFromCoords} 4 | \alias{findPentadFromCoords} 5 | \title{Find the ABAP pentad that contains a spatial location} 6 | \usage{ 7 | findPentadFromCoords(x, y) 8 | } 9 | \arguments{ 10 | \item{x}{Longitude of the point contained by the pentad, in decimal degrees.} 11 | 12 | \item{y}{Longitude of the point contained by the pentad, in decimal degrees.} 13 | } 14 | \value{ 15 | The code of the pentad containing the location defined by \code{x} and \code{y}. 16 | } 17 | \description{ 18 | Find the ABAP pentad that contains a spatial location 19 | } 20 | \examples{ 21 | findPentadFromCoords(-25.68606, 29.011337) 22 | } 23 | -------------------------------------------------------------------------------- /man/jsonToTibble.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/jsonToTibble.R 3 | \name{jsonToTibble} 4 | \alias{jsonToTibble} 5 | \title{Helper function to transform a JSON object to a tibble} 6 | \usage{ 7 | jsonToTibble(jsonfile) 8 | } 9 | \arguments{ 10 | \item{jsonfile}{An object obtained when a JSON file is downloaded} 11 | } 12 | \value{ 13 | A tibble 14 | } 15 | \description{ 16 | Helper function to transform a JSON object to a tibble 17 | } 18 | \examples{ 19 | url <- "http://api.adu.org.za/cwac/sites/list?province=north20\%west" 20 | myfile <- httr::RETRY("GET", url) \%>\% 21 | httr::content(as = "text", encoding = "UTF-8") 22 | jsonfile <- rjson::fromJSON(myfile) 23 | jsonToTibble(jsonfile) 24 | } 25 | -------------------------------------------------------------------------------- /tests/testthat/test-addVarEEimage.R: -------------------------------------------------------------------------------- 1 | test_that("returns a deprecation message", { 2 | lifecycle::expect_deprecated(addVarEEimage(ee_pentads = ee_data, 3 | image = "JRC/GSW1_3/GlobalSurfaceWater", 4 | reducer = "mean", 5 | bands = "occurrence")) 6 | }) 7 | 8 | 9 | test_that("informs about an alternative", { 10 | expect_message(addVarEEimage(ee_pentads = ee_data, 11 | image = "JRC/GSW1_3/GlobalSurfaceWater", 12 | reducer = "mean", 13 | bands = "occurrence"), 14 | regexp = "This function has been discontinued. Please, use ABDtools::addVarEEimage() instead", 15 | fixed = TRUE) 16 | }) 17 | -------------------------------------------------------------------------------- /R/jsonToTibble.R: -------------------------------------------------------------------------------- 1 | #' Helper function to transform a JSON object to a tibble 2 | #' 3 | #' @param jsonfile An object obtained when a JSON file is downloaded 4 | #' 5 | #' @return A tibble 6 | #' @export 7 | #' @examples 8 | #' url <- "http://api.adu.org.za/cwac/sites/list?province=north20%west" 9 | #' myfile <- httr::RETRY("GET", url) %>% 10 | #' httr::content(as = "text", encoding = "UTF-8") 11 | #' jsonfile <- rjson::fromJSON(myfile) 12 | #' jsonToTibble(jsonfile) 13 | jsonToTibble <- function(jsonfile){ 14 | 15 | out <- jsonfile %>% 16 | lapply(function(x) { 17 | x[sapply(x, is.null)] <- NA 18 | x <- unlist(x) 19 | x[x == "N/A"] <- NA 20 | cnames <- names(x) 21 | df <- data.frame() 22 | df <- rbind(df, x) 23 | names(df) <- cnames 24 | return(df) 25 | }) %>% 26 | dplyr::bind_rows() %>% 27 | dplyr::as_tibble() 28 | 29 | return(out) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /R/getCardRecords.R: -------------------------------------------------------------------------------- 1 | #' Download the list of records from an ABAP card 2 | #' 3 | #' @param .CardNo An ABAP card code 4 | #' 5 | #' @return A tibble in which each row corresponds to an entry to an ABAP card. 6 | #' @export 7 | #' 8 | #' @examples 9 | #' getCardRecords("3335_2320_011617_20211219") 10 | getCardRecords <- function(.CardNo){ 11 | 12 | url <- paste0("https://api.birdmap.africa/sabap2/v2/card/full/0/", .CardNo) 13 | 14 | # Extract data 15 | myfile <- httr::RETRY("GET", url) %>% 16 | httr::content(as = "text", encoding = "UTF-8") 17 | 18 | jsonfile <- rjson::fromJSON(myfile) 19 | 20 | out <- jsonfile$data$cards[[1]]$records %>% 21 | dplyr::bind_rows() %>% 22 | dplyr::as_tibble() 23 | 24 | if(sum(dim(out)) == 0){ 25 | warning("There are no species records for that entry. You may need to check the card number.") 26 | } 27 | 28 | return(out) 29 | 30 | } 31 | -------------------------------------------------------------------------------- /man/searchAbapSpecies.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/searchAbapSpecies.R 3 | \name{searchAbapSpecies} 4 | \alias{searchAbapSpecies} 5 | \title{Search species in ABAP data base} 6 | \usage{ 7 | searchAbapSpecies(species) 8 | } 9 | \arguments{ 10 | \item{species}{A character string with any part of the common or taxonomic 11 | name, or, the SAFRING code. Note that full names will 12 | not work; choose a single word.} 13 | } 14 | \value{ 15 | A tibble with taxonomic information and codes of all species 16 | matching the search. At the moment, if a species code is passed, the new API 17 | is used. For convenience functionality for entering a common name is 18 | maintained through the old API, but this might be discontinued. 19 | } 20 | \description{ 21 | Search species in ABAP data base 22 | } 23 | \examples{ 24 | searchAbapSpecies("Duck") 25 | searchAbapSpecies(169) 26 | searchAbapSpecies("Fulvous") 27 | } 28 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ABAP 2 | Title: Access to African Bird Atlas Project data from R 3 | Version: 0.6.2 4 | Authors@R: 5 | person(given = "BIRDIE Development Team", 6 | role = c("aut", "cre"), 7 | email = "f.cervantesperalta@gmail.com", 8 | comment = c(ORCID = "YOUR-ORCID-ID")) 9 | Description: This package provides functions to access the ABAP server API and 10 | download data. 11 | License: MIT + file LICENSE 12 | Encoding: UTF-8 13 | LazyData: true 14 | Roxygen: list(markdown = TRUE) 15 | RoxygenNote: 7.3.2 16 | Imports: 17 | dplyr, 18 | httr, 19 | lifecycle, 20 | lubridate, 21 | magrittr, 22 | readr, 23 | rjson, 24 | rlang, 25 | sf, 26 | tidyr 27 | Depends: 28 | R (>= 2.10) 29 | URL: https://github.com/AfricaBirdData/ABAP 30 | Suggests: 31 | data.table, 32 | spOccupancy, 33 | testthat (>= 3.0.0), 34 | ubms, 35 | unmarked 36 | Config/testthat/edition: 3 37 | -------------------------------------------------------------------------------- /tests/testthat/helper.R: -------------------------------------------------------------------------------- 1 | # Most things in this package depend on the birdmap API being reachable 2 | skip_if_offline(host = "api.birdmap.africa") 3 | 4 | # Selection of species to test 5 | spp <- c(95, 10015, 91, 103, 1016, 96, 89, 88, 102, 92, 1342, 1340, 90, 94, 98, 99, 6 | 97, 101, 104, 100, 274, 236, 233, 239, 237, 955, 238, 235, 245, 248, 246, 240, 7 | 241, 273, 282, 281, 231, 228, 229, 288, 289, 287, 4136, 2058, 306, 292, 8 | 294, 903, 290, 291, 300, 297, 299, 293, 296, 298, 305, 304, 269, 270, 230, 9 | 254, 256, 255, 258, 251, 259, 262, 257, 264, 250, 253, 232, 267, 266, 265, 263, 10 | 268, 52, 66, 67, 61, 58, 59, 4150, 60, 64, 55, 56, 63, 54, 57, 65, 62, 69, 70, 74, 11 | 79, 73, 75, 77, 76, 42, 41, 49, 48, 51, 50, 47, 86, 87, 5, 4, 6, 72, 81, 83, 84, 85, 12 | 396, 397, 394, 395, 400, 149, 167, 166, 172, 216, 214, 215, 213, 199, 202, 203, 205, 13 | 207, 209, 210, 211, 197, 208, 212, 370, 361, 360) 14 | 15 | 16 | # Selection of years to test 17 | years <- 2008:2022 18 | -------------------------------------------------------------------------------- /tests/testthat/test-addVarEEclosestImage.R: -------------------------------------------------------------------------------- 1 | test_that("returns a deprecation message", { 2 | lifecycle::expect_deprecated(addVarEEclosestImage(ee_pentads = ee_data, 3 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 4 | reducer = "mean", 5 | maxdiff = 15, 6 | bands = c("tmmn"))) 7 | }) 8 | 9 | 10 | test_that("informs about an alternative", { 11 | expect_message(addVarEEclosestImage(ee_pentads = ee_data, 12 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 13 | reducer = "mean", 14 | maxdiff = 15, 15 | bands = c("tmmn")), 16 | regexp = "This function has been discontinued. Please, use ABDtools::addVarEEclosestImage() instead", 17 | fixed = TRUE) 18 | }) 19 | 20 | 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2021 BIRDIE Development Team 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/testthat/test-addVarEEcollection.R: -------------------------------------------------------------------------------- 1 | test_that("returns a deprecation message", { 2 | lifecycle::expect_deprecated(addVarEEcollection(ee_pentads = ee_data, 3 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 4 | dates = c("2010-01-01", "2011-01-01"), 5 | temp_reducer = "mean", 6 | spt_reducer = "mean", 7 | bands = "tmmn")) 8 | }) 9 | 10 | 11 | test_that("informs about an alternative", { 12 | expect_message(addVarEEcollection(ee_pentads = ee_data, 13 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 14 | dates = c("2010-01-01", "2011-01-01"), 15 | temp_reducer = "mean", 16 | spt_reducer = "mean", 17 | bands = "tmmn"), 18 | regexp = "This function has been discontinued. Please, use ABDtools::addVarEEcollection() instead", 19 | fixed = TRUE) 20 | }) 21 | -------------------------------------------------------------------------------- /R/findPentadFromCoords.R: -------------------------------------------------------------------------------- 1 | #' Find the ABAP pentad that contains a spatial location 2 | #' 3 | #' @param x Longitude of the point contained by the pentad, in decimal degrees. 4 | #' @param y Longitude of the point contained by the pentad, in decimal degrees. 5 | #' 6 | #' @return The code of the pentad containing the location defined by `x` and `y`. 7 | #' @export 8 | #' 9 | #' @examples 10 | #' findPentadFromCoords(-25.68606, 29.011337) 11 | findPentadFromCoords <- function(x, y){ 12 | 13 | x <- abs(x) 14 | x1 <- floor(6 * (x - floor(x))) 15 | 16 | if(x1 == 0){ 17 | x2 <- floor(60 * (x - floor(x))) 18 | } else { 19 | x2 <- floor(60 * (x - floor(x))) %% (x1 * 10) 20 | } 21 | 22 | x2 <- ifelse(x2 < 5, 0, 5) 23 | 24 | x <- paste(floor(x), x1, x2, sep="") 25 | 26 | y1 <- floor(6 * (y - floor(y))) 27 | 28 | if(y1 == 0){ 29 | y2 <- floor(60 * (y - floor(y))) 30 | } else { 31 | y2 <- floor(60 * (y - floor(y))) %% (y1 * 10) 32 | } 33 | 34 | y2 <- ifelse(y2 < 5, 0, 5) 35 | 36 | y <- paste(floor(y), y1, y2, sep="") 37 | 38 | paste(x, "_", y, sep = "") 39 | 40 | # return(paste(x, "_", y, sep="")) 41 | # rm(x, x1, x2, y, y1, y2) 42 | 43 | } 44 | -------------------------------------------------------------------------------- /R/searchAbapSpecies.R: -------------------------------------------------------------------------------- 1 | 2 | #' Search species in ABAP data base 3 | #' 4 | #' @param species A character string with any part of the common or taxonomic 5 | #' name, or, the SAFRING code. Note that full names will 6 | #' not work; choose a single word. 7 | #' 8 | #' @return A tibble with taxonomic information and codes of all species 9 | #' matching the search. At the moment, if a species code is passed, the new API 10 | #' is used. For convenience functionality for entering a common name is 11 | #' maintained through the old API, but this might be discontinued. 12 | #' @export 13 | #' 14 | #' @examples 15 | #' searchAbapSpecies("Duck") 16 | #' searchAbapSpecies(169) 17 | #' searchAbapSpecies("Fulvous") 18 | searchAbapSpecies <- function(species){ 19 | 20 | url <- paste0("https://api.birdmap.africa/sabap2/v2/search/species/", species) 21 | 22 | # Extract data 23 | myfile <- httr::RETRY("GET", url) %>% 24 | httr::content(as = "text", encoding = "UTF-8") 25 | 26 | if(myfile == ""){ 27 | stop("We couldn't retrieve your querry. Please check your spelling and try again.") 28 | } 29 | 30 | jsonfile <- rjson::fromJSON(myfile) 31 | 32 | # Reformat 33 | out <- ABAP::jsonToTibble(jsonfile$data) 34 | 35 | return(out) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /man/getRegionPentads.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getRegionPentads.R 3 | \name{getRegionPentads} 4 | \alias{getRegionPentads} 5 | \title{Get ABAP pentads for a certain region} 6 | \usage{ 7 | getRegionPentads(.region_type, .region) 8 | } 9 | \arguments{ 10 | \item{.region_type}{The type of region we are interested on. 11 | Three options: "country", "province", "project" and "pentad".} 12 | 13 | \item{.region}{A character string corresponding to the specific region we are 14 | interested in. It can be either a country in Southern Africa, a South African 15 | province, a project (currently, "SABAP1" or "SABAP2") or a pentad code.} 16 | } 17 | \value{ 18 | A simple feature object with those pentads that are contained in the 19 | region of interest. A pentads is considered contained if half of its area 20 | lies within the region. 21 | } 22 | \description{ 23 | Get ABAP pentads for a certain region 24 | } 25 | \details{ 26 | At the moment, ABAP serves data from eleven countries: South Africa, 27 | Botswana, eSwatini, Lesotho, Malawi, Mozambique, Namibia, Zambia, Zimbabwe, 28 | Kenya and Nigeria. Only South African provinces are available: Western Cape, 29 | Eastern Cape, Northern Cape, Free State, Limpopo, Mpumalanga, KwaZulu-Natal, 30 | Gauteng, and Northwest Province. 31 | } 32 | \examples{ 33 | # getRegionPentads(.region_type = "country", .region = "South Africa") 34 | } 35 | -------------------------------------------------------------------------------- /tests/testthat/test-getRegionPentads.R: -------------------------------------------------------------------------------- 1 | # For the selection of species and years that we can use for testing see 2 | # tests/testthat/helper.R 3 | 4 | test_that("we get an sf object", { 5 | 6 | my_data <- getRegionPentads(.region_type = "province", 7 | .region = "Western Cape") 8 | 9 | expect_s3_class(my_data, "sf") 10 | 11 | }) 12 | 13 | # For the next tests we need a standard to match the outputs of getRegionPentads() 14 | # against. This is found at tests/testthat/fixtures/empty_pentad_df_yyyymmdd.rds 15 | # where yyyymmdd is the data of the last file to use as reference. If the 16 | # standard changed, we would need to generate a new file with the new standard 17 | # and the new date. It would be good to keep all standards for future comparison 18 | 19 | test_that("we get the correct number of columns", { 20 | 21 | my_data <- getRegionPentads(.region_type = "province", 22 | .region = "Western Cape") 23 | 24 | ref_data <- readRDS(test_path("fixtures", "empty_pentad_df_20231003.rds")) 25 | 26 | expect_equal(ncol(my_data), ncol(ref_data)) 27 | 28 | }) 29 | 30 | 31 | test_that("we get the correct types of columns", { 32 | 33 | my_data <- getRegionPentads(.region_type = "province", 34 | .region = "Western Cape") 35 | 36 | ref_data <- readRDS(test_path("fixtures", "empty_pentad_df_20231003.rds")) 37 | 38 | expect_equal(sapply(my_data, class), sapply(ref_data, class)) 39 | 40 | }) 41 | -------------------------------------------------------------------------------- /tests/testthat/test-EEcollectionToMultiband.R: -------------------------------------------------------------------------------- 1 | test_that("returns a deprecation message", { 2 | lifecycle::expect_deprecated(EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 3 | dates = c("2008-01-01", "2020-01-01"), 4 | band = "NDVI", # You can find what bands are available from GEE catalog 5 | group_type = "year", 6 | groups = 2008:2019, 7 | reducer = "mean", 8 | unmask = FALSE)) 9 | }) 10 | 11 | 12 | test_that("informs about an alternative", { 13 | expect_message(EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 14 | dates = c("2008-01-01", "2020-01-01"), 15 | band = "NDVI", # You can find what bands are available from GEE catalog 16 | group_type = "year", 17 | groups = 2008:2019, 18 | reducer = "mean", 19 | unmask = FALSE), 20 | regexp = "This function has been discontinued. Please, use ABDtools::EEcollectionToMultiband() instead", 21 | fixed = TRUE) 22 | }) 23 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v3 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: test-coverage 10 | 11 | jobs: 12 | test-coverage: 13 | runs-on: ubuntu-latest 14 | env: 15 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | 20 | - uses: r-lib/actions/setup-r@v2 21 | with: 22 | use-public-rspm: true 23 | 24 | - uses: r-lib/actions/setup-r-dependencies@v2 25 | with: 26 | extra-packages: any::covr 27 | needs: coverage 28 | 29 | - name: Test coverage 30 | run: | 31 | covr::codecov( 32 | quiet = FALSE, 33 | clean = FALSE, 34 | install_path = file.path(Sys.getenv("RUNNER_TEMP"), "package") 35 | ) 36 | shell: Rscript {0} 37 | 38 | - name: Show testthat output 39 | if: always() 40 | run: | 41 | ## -------------------------------------------------------------------- 42 | find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \; || true 43 | shell: bash 44 | 45 | - name: Upload test results 46 | if: failure() 47 | uses: actions/upload-artifact@v3 48 | with: 49 | name: coverage-test-failures 50 | path: ${{ runner.temp }}/package 51 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # ABAP 0.6.2 2 | 3 | - Added regions available to documentation 4 | 5 | # ABAP 0.6.1 6 | 7 | - Added documentation explaining visit data variables 8 | 9 | # ABAP 0.6.0 10 | 11 | - Added pentad "group" as a region option for getAbapData 12 | 13 | # ABAP 0.5.0 14 | 15 | - Google Earth Engine-related functions no longer work. Now there is a message 16 | pointing to ABDtools 17 | 18 | # ABAP 0.4.1 19 | 20 | - searchAbapSpecies() uses a single API call for all requests. This implies that field names might have changed 21 | 22 | # ABAP 0.4.0 23 | 24 | - Added abapToOccuR() 25 | 26 | - Removed rgee as a dependency. It is now a dependency of ABDtools package 27 | 28 | # ABAP 0.3.0 29 | 30 | - Deprecated ABAP-rgee functions (use ABDtools now) 31 | 32 | - Added function to prepare spOccupancy multi-season data 33 | 34 | # ABAP 0.2.0 35 | 36 | - Added function to download all cards from a given pentad 37 | 38 | - Added function to find a pentad from lon-lat coordinates 39 | 40 | - Eliminated dependency from data.table 41 | 42 | # ABAP 0.1.1 43 | 44 | - Speed up 'abapTo' functions 45 | 46 | - spOccupancy and unmarked objects are ordered by pentad 47 | 48 | # ABAP 0.1.0 49 | 50 | - Set a standard for variables coming out of Google Earth Engine images. Variables will always be named as "\\_\". **Note that this change could break some existing code** 51 | 52 | - Added functions to format ABAP data into objects used by popular occupancy modelling R packages, such as *unmarked* or *spOccupancy*. 53 | 54 | # ABAP 0.0.5 55 | 56 | - Added a `NEWS.md` file to track changes to the package. 57 | - rgee:: called explicitly 58 | -------------------------------------------------------------------------------- /R/abap_visit_vars.R: -------------------------------------------------------------------------------- 1 | #' Empty data frame with ABAP visit-level variables 2 | #' 3 | #' @description An empty dataset containing all variables associated with ABAP 4 | #' visit data downloaded with \code{\link{getAbapData}}. 5 | 6 | #' @format A data frame with 0 rows and 39 variables: 7 | #' \describe{ 8 | #' \item{CardNo}{Card number} 9 | #' \item{StartDate}{Date when the card was started} 10 | #' \item{EndDate}{Date when the card was closed} 11 | #' \item{StartTime}{Date when the card was started} 12 | #' \item{Pentad}{Pentad the card corresponds to} 13 | #' \item{ObserverNo}{Observer ID number} 14 | #' \item{TotalHours}{Total number of hours spent birding} 15 | #' \item{Hour1}{Total number of species up to hour 1} 16 | #' \item{Hour2}{Total number of species up to hour 2} 17 | #' \item{Hour3}{Total number of species up to hour 3} 18 | #' \item{Hour4}{Total number of species up to hour 4} 19 | #' \item{Hour5}{Total number of species up to hour 5} 20 | #' \item{Hour6}{Total number of species up to hour 6} 21 | #' \item{Hour7}{Total number of species up to hour 7} 22 | #' \item{Hour8}{Total number of species up to hour 8} 23 | #' \item{Hour9}{Total number of species up to hour 9} 24 | #' \item{Hour10}{Total number of species up to hour 10} 25 | #' \item{TotalSpp}{Total number of species detected} 26 | #' \item{InclNight}{Whether surveys were conducted at night} 27 | #' \item{AllHabitats}{Whether all habitats were surveyed} 28 | #' \item{Spp}{A species code if it was detected, "-" otherwise} 29 | #' \item{Sequence}{Sequence in which the species was detected} 30 | #' \item{Common_name}{Common_name of the species} 31 | #' \item{Taxonomic_name}{Taxonomic_name of the species} 32 | #' } 33 | "abap_visit_vars" 34 | -------------------------------------------------------------------------------- /beta/abapTo.R: -------------------------------------------------------------------------------- 1 | #' Format ABAP data for other packages 2 | #' 3 | #' @description Format raw data coming from ABAP to be used on other packages 4 | #' that provide functionality for occupancy analysis. 5 | #' @param abap_data ABAP data downloaded using \code{\link{getAbapData}} 6 | #' @param to A character string with the package data must be format to. Currently, 7 | #' the options are: "unmarked" and "spOccupancy". 8 | #' @param season A character string defining whether the data must be prepared 9 | #' for single season or multiple season occupancy analysis. 10 | #' @param pentads an `sf` object returned by \code{\link{getRegionPentads}}. Defaults to `NULL`. 11 | #' 12 | #' @return An object of the target package 13 | #' @export 14 | #' 15 | #' @examples 16 | #' abap_single <- getAbapData(.spp_code = 212, 17 | #' .region_type = "province", 18 | #' .region = "Eastern Cape", 19 | #' .years = 2012) 20 | #' 21 | #' um_single_df <- abapTo(abap_single, to = "unmarked", season = "single") 22 | #' spOcc_single_df <- abapTo(abap_single, to = "spOccupancy", season = "single") 23 | abapTo <- function(abap_data, to = c("unmarked", "spOccupancy"), season = c("single", "multi"), 24 | pentads = NULL){ 25 | 26 | if(length(to) > 1){ 27 | to <- "unmarked" 28 | } 29 | 30 | if(length(season) > 1){ 31 | season <- "single" 32 | } 33 | 34 | if(to == "unmarked" & season == "single"){ 35 | out <- abapToUnmarked_single(abap_data, pentads) 36 | } 37 | 38 | if(to == "unmarked" & season == "multi"){ 39 | out <- abapToUnmarked_multi(abap_data) 40 | } 41 | 42 | if(to == "spOccupancy" & season == "single"){ 43 | out <- abapToSpOcc_single(abap_data, pentads) 44 | } 45 | 46 | return(out) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /man/abap_visit_vars.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abap_visit_vars.R 3 | \docType{data} 4 | \name{abap_visit_vars} 5 | \alias{abap_visit_vars} 6 | \title{Empty data frame with ABAP visit-level variables} 7 | \format{ 8 | A data frame with 0 rows and 39 variables: 9 | \describe{ 10 | \item{CardNo}{Card number} 11 | \item{StartDate}{Date when the card was started} 12 | \item{EndDate}{Date when the card was closed} 13 | \item{StartTime}{Date when the card was started} 14 | \item{Pentad}{Pentad the card corresponds to} 15 | \item{ObserverNo}{Observer ID number} 16 | \item{TotalHours}{Total number of hours spent birding} 17 | \item{Hour1}{Total number of species up to hour 1} 18 | \item{Hour2}{Total number of species up to hour 2} 19 | \item{Hour3}{Total number of species up to hour 3} 20 | \item{Hour4}{Total number of species up to hour 4} 21 | \item{Hour5}{Total number of species up to hour 5} 22 | \item{Hour6}{Total number of species up to hour 6} 23 | \item{Hour7}{Total number of species up to hour 7} 24 | \item{Hour8}{Total number of species up to hour 8} 25 | \item{Hour9}{Total number of species up to hour 9} 26 | \item{Hour10}{Total number of species up to hour 10} 27 | \item{TotalSpp}{Total number of species detected} 28 | \item{InclNight}{Whether surveys were conducted at night} 29 | \item{AllHabitats}{Whether all habitats were surveyed} 30 | \item{Spp}{A species code if it was detected, "-" otherwise} 31 | \item{Sequence}{Sequence in which the species was detected} 32 | \item{Common_name}{Common_name of the species} 33 | \item{Taxonomic_name}{Taxonomic_name of the species} 34 | } 35 | } 36 | \usage{ 37 | abap_visit_vars 38 | } 39 | \description{ 40 | An empty dataset containing all variables associated with ABAP 41 | visit data downloaded with \code{\link{getAbapData}}. 42 | } 43 | \keyword{datasets} 44 | -------------------------------------------------------------------------------- /tests/testthat/test-getCardRecords.R: -------------------------------------------------------------------------------- 1 | # For the selection of species and years that we can use for testing see 2 | # tests/testthat/helper.R 3 | 4 | test_that("we get a tibble", { 5 | 6 | my_data <- getAbapData(sample(spp, 1), 7 | .region_type = "province", 8 | .region = "Western Cape", 9 | .years = sample(years, 1)) 10 | 11 | my_card <- my_data$CardNo[1] 12 | 13 | card_data <- getCardRecords(my_card) 14 | 15 | expect_s3_class(card_data, "tbl_df") 16 | 17 | }) 18 | 19 | 20 | # For the next tests we need a standard to match the outputs of getCardRecords() 21 | # against. This is found at tests/testthat/fixtures/empty_card_df_yyyymmdd.rds 22 | # where yyyymmdd is the data of the last file to use as reference. If the 23 | # standard changed, we would need to generate a new file with the new standard 24 | # and the new date. It would be good to keep all standards for future comparison 25 | 26 | test_that("we get the correct number of columns", { 27 | 28 | my_data <- getAbapData(sample(spp, 1), 29 | .region_type = "province", 30 | .region = "Western Cape", 31 | .years = sample(years, 1)) 32 | 33 | my_card <- my_data$CardNo[1] 34 | 35 | card_data <- getCardRecords(my_card) 36 | 37 | ref_data <- readRDS(test_path("fixtures", "empty_card_df_20231003.rds")) 38 | 39 | expect_equal(ncol(card_data), ncol(ref_data)) 40 | 41 | }) 42 | 43 | 44 | test_that("we get the correct types of columns", { 45 | 46 | my_data <- getAbapData(sample(spp, 1), 47 | .region_type = "province", 48 | .region = "Western Cape", 49 | .years = sample(years, 1)) 50 | 51 | my_card <- my_data$CardNo[1] 52 | 53 | card_data <- getCardRecords(my_card) 54 | 55 | ref_data <- readRDS(test_path("fixtures", "empty_card_df_20231003.rds")) 56 | 57 | expect_equal(sapply(card_data, class), sapply(ref_data, class)) 58 | 59 | }) 60 | -------------------------------------------------------------------------------- /R/getRegionPentads.R: -------------------------------------------------------------------------------- 1 | #' Get ABAP pentads for a certain region 2 | #' 3 | #' @param .region_type The type of region we are interested on. 4 | #' Three options: "country", "province", "project" and "pentad". 5 | #' @param .region A character string corresponding to the specific region we are 6 | #' interested in. It can be either a country in Southern Africa, a South African 7 | #' province, a project (currently, "SABAP1" or "SABAP2") or a pentad code. 8 | #' 9 | #' @details At the moment, ABAP serves data from eleven countries: South Africa, 10 | #' Botswana, eSwatini, Lesotho, Malawi, Mozambique, Namibia, Zambia, Zimbabwe, 11 | #' Kenya and Nigeria. Only South African provinces are available: Western Cape, 12 | #' Eastern Cape, Northern Cape, Free State, Limpopo, Mpumalanga, KwaZulu-Natal, 13 | #' Gauteng, and Northwest Province. 14 | #' 15 | #' @return A simple feature object with those pentads that are contained in the 16 | #' region of interest. A pentads is considered contained if half of its area 17 | #' lies within the region. 18 | #' @export 19 | #' 20 | #' @examples 21 | #' # getRegionPentads(.region_type = "country", .region = "South Africa") 22 | getRegionPentads <- function(.region_type, .region){ 23 | 24 | .region_type <- tolower(.region_type) 25 | .region <- tolower(.region) 26 | .region <- gsub(" ", "", .region) 27 | 28 | url <- paste0("https://api.birdmap.africa/sabap2/v2/pentads/", .region_type, 29 | "/", .region, "?format=geoJSON") 30 | 31 | # Download geojson data 32 | geojson_file <- httr::GET(url) 33 | geojson_content <- httr::content(geojson_file, encoding = "UTF-8", as = "text") 34 | 35 | # Extract data 36 | pentads <- sf::read_sf(geojson_content) 37 | 38 | # Clean and return 39 | pentads <- pentads %>% 40 | dplyr::rename_with(.fn = ~gsub(".", "_", .x, fixed = TRUE)) # remove points in names (GEE doesn't like) 41 | 42 | if(!is.null(pentads$format)){ 43 | pentads <- pentads %>% 44 | dplyr::select(-format) 45 | } 46 | 47 | return(pentads) 48 | } 49 | 50 | -------------------------------------------------------------------------------- /man/addVarEEimage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addVarEEimage.R 3 | \name{addVarEEimage} 4 | \alias{addVarEEimage} 5 | \title{Add variable from Google Earth Engine Image} 6 | \usage{ 7 | addVarEEimage(ee_pentads, image, reducer, bands = NULL, unmask = FALSE) 8 | } 9 | \arguments{ 10 | \item{ee_pentads}{A feature collection with the pentads we want to annotate. 11 | We need to upload an sf object with the pentads to GEE.} 12 | 13 | \item{image}{Either a character string with the name of the image we want to 14 | use or an GEE image produced with \code{ee$Image()}. See 15 | \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}.} 16 | 17 | \item{reducer}{A character string specifying the function apply when 18 | extracting values for each pentad. It is common to use "mean", "sum" or 19 | "count". But there are many other, see 'ee.Reducer' under Client Libraries at 20 | \url{https://developers.google.com/earth-engine/apidocs}.} 21 | 22 | \item{bands}{Select specific bands from the image. If not specified, pentads 23 | will be annotated with all bands (one column for each band).} 24 | 25 | \item{unmask}{GEE masks missing values, which means they are not used for 26 | computing means, counts, etc. Sometimes we might want to avoid this behaviour 27 | and use 0 instead of NA. If so, set unmask to TRUE.} 28 | } 29 | \value{ 30 | A dataframe similar to \code{ee_pentads} with variables added from the 31 | \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 32 | the name of the new variables will be the selected band (\code{bands} or else 33 | all bands from \code{collection} followed by the spatial reducer \code{reducer}. 34 | } 35 | \description{ 36 | Add variable from Google Earth Engine Image 37 | } 38 | \examples{ 39 | \dontrun{ 40 | # Load the remote data asset 41 | ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 42 | 43 | # Annotate with surface water occurrence image 44 | pentads_tmmn <- addVarEEimage(ee_pentads = ee_data, 45 | image = "JRC/GSW1_3/GlobalSurfaceWater", 46 | reducer = "mean", 47 | bands = "occurrence") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /man/uploadPentadsToEE.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/uploadPentadsToEE.R 3 | \name{uploadPentadsToEE} 4 | \alias{uploadPentadsToEE} 5 | \title{Upload pentads to Google Earth Engine server} 6 | \usage{ 7 | uploadPentadsToEE(pentads, asset_id, load = TRUE, max_p = 16250) 8 | } 9 | \arguments{ 10 | \item{pentads}{An \href{https://github.com/r-spatial/sf}{sf} object with the pentads to upload} 11 | 12 | \item{asset_id}{A character string with the name we want our pentads to be 13 | saved on the server with.} 14 | 15 | \item{load}{If TRUE (default), the GEE asset is loaded into the R session.} 16 | 17 | \item{max_p}{Maximum number of pentads the function will try to upload 18 | without splitting into pieces. The default is a sensible choice but you can 19 | try modify it to serve your purposes.} 20 | } 21 | \value{ 22 | Pentads are uploaded to GEE. In addition a GEE feature collection can 23 | be loaded into the R environment 24 | } 25 | \description{ 26 | Upload pentads to Google Earth Engine server 27 | } 28 | \details{ 29 | An \href{https://github.com/r-spatial/sf}{sf} object is uploaded to GEE servers via 30 | "getInfo_to_asset" (see \link[rgee]{sf_as_ee}). If there are many pentads, 31 | the function will upload to objects and merge them in the server under the 32 | name provided. Please be conscious that two intermediate objects will also 33 | be stored under names "p1" and "p2". We recommend visiting your account and 34 | cleaning unnecesary objects regularly. 35 | } 36 | \examples{ 37 | \dontrun{ 38 | # Load ABAP pentads 39 | pentads <- getRegionPentads(.region_type = "province", .region = "North West") 40 | 41 | # Set an ID for your remote asset (data in GEE) 42 | assetId <- sprintf("\%s/\%s", ee_get_assethome(), 'pentads') 43 | 44 | # Upload to GEE (if not done already - do this only once per asset) 45 | uploadPentadsToEE(pentads = pentads, 46 | asset_id = assetId, 47 | load = FALSE) 48 | 49 | # Load the remote asset to you local computer to work with it 50 | ee_pentads <- ee$FeatureCollection(assetId) 51 | 52 | # Alternatively we can upload to GEE and load the asset in one call 53 | ee_pentads <- uploadPentadsToEE(pentads = pentads, 54 | asset_id = assetId, 55 | load = TRUE) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/testthat/test-getAbapData.R: -------------------------------------------------------------------------------- 1 | # For the selection of species and years that we can use for testing see 2 | # tests/testthat/helper.R 3 | 4 | test_that("we get a tibble", { 5 | 6 | my_data <- getAbapData(sample(spp, 1), 7 | .region_type = "province", 8 | .region = "Western Cape", 9 | .years = sample(years, 1)) 10 | 11 | expect_s3_class(my_data, "tbl_df") 12 | 13 | }) 14 | 15 | # For the next tests we need a standard to match the outputs of getAbapData() 16 | # against. This is found at tests/testthat/fixtures/empty_abap_df_yyyymmdd.rds 17 | # where yyyymmdd is the data of the last file to use as reference. If the 18 | # standard changed, we would need to generate a new file with the new standard 19 | # and the new date. It would be good to keep all standards for future comparison 20 | 21 | test_that("we get the correct number of columns", { 22 | 23 | my_data <- getAbapData(sample(spp, 1), 24 | .region_type = "province", 25 | .region = "Western Cape", 26 | .years = sample(years, 1)) 27 | 28 | ref_data <- readRDS(test_path("fixtures", "empty_abap_df_20231003.rds")) 29 | 30 | expect_equal(ncol(my_data), ncol(ref_data)) 31 | 32 | }) 33 | 34 | 35 | test_that("we get the correct types of columns", { 36 | 37 | my_data <- getAbapData(sample(spp, 1), 38 | .region_type = "province", 39 | .region = "Western Cape", 40 | .years = sample(years, 1)) 41 | 42 | ref_data <- readRDS(test_path("fixtures", "empty_abap_df_20231003.rds")) 43 | 44 | expect_equal(sapply(my_data, class), sapply(ref_data, class)) 45 | 46 | }) 47 | 48 | 49 | test_that("different species only differ in the last four columns", { 50 | 51 | species <- sample(spp, 2, replace = FALSE) 52 | year <- sample(years, 1) 53 | 54 | data1 <- getAbapData(species[1], 55 | .region_type = "province", 56 | .region = "Western Cape", 57 | .years = year) 58 | 59 | data2 <- getAbapData(species[2], 60 | .region_type = "province", 61 | .region = "Western Cape", 62 | .years = year) 63 | 64 | expect_equal(data1[,1:20], data2[,1:20]) 65 | 66 | }) 67 | -------------------------------------------------------------------------------- /R/addVarEEimage.R: -------------------------------------------------------------------------------- 1 | #' Add variable from Google Earth Engine Image 2 | #' 3 | #' @param ee_pentads A feature collection with the pentads we want to annotate. 4 | #' We need to upload an sf object with the pentads to GEE. 5 | #' @param image Either a character string with the name of the image we want to 6 | #' use or an GEE image produced with \code{ee$Image()}. See 7 | #' \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}. 8 | #' @param reducer A character string specifying the function apply when 9 | #' extracting values for each pentad. It is common to use "mean", "sum" or 10 | #' "count". But there are many other, see 'ee.Reducer' under Client Libraries at 11 | #' \url{https://developers.google.com/earth-engine/apidocs}. 12 | #' @param bands Select specific bands from the image. If not specified, pentads 13 | #' will be annotated with all bands (one column for each band). 14 | #' @param unmask GEE masks missing values, which means they are not used for 15 | #' computing means, counts, etc. Sometimes we might want to avoid this behaviour 16 | #' and use 0 instead of NA. If so, set unmask to TRUE. 17 | #' 18 | #' @return A dataframe similar to \code{ee_pentads} with variables added from the 19 | #' \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 20 | #' the name of the new variables will be the selected band (\code{bands} or else 21 | #' all bands from \code{collection} followed by the spatial reducer \code{reducer}. 22 | #' @export 23 | #' 24 | #' @examples 25 | #' \dontrun{ 26 | #' # Load the remote data asset 27 | #' ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 28 | #' 29 | #'# Annotate with surface water occurrence image 30 | #' pentads_tmmn <- addVarEEimage(ee_pentads = ee_data, 31 | #' image = "JRC/GSW1_3/GlobalSurfaceWater", 32 | #' reducer = "mean", 33 | #' bands = "occurrence") 34 | #' } 35 | addVarEEimage <- function(ee_pentads, image, reducer, 36 | bands = NULL, unmask = FALSE){ 37 | 38 | lifecycle::deprecate_warn( 39 | when = "0.3.0", 40 | what = "ABAP::addVarEEimage()", 41 | with = "ABDtools::addVarEEimage()", 42 | details = "A new version of addVarEEimage() is now on package ABDtools (https://github.com/AfricaBirdData/ABDtools). 43 | The ABAP function has been discontinued", 44 | id = NULL, 45 | always = FALSE, 46 | env = rlang::caller_env(), 47 | user_env = rlang::caller_env(2) 48 | ) 49 | 50 | message("This function has been discontinued. Please, use ABDtools::addVarEEimage() instead") 51 | message("(https://github.com/AfricaBirdData/ABDtools)") 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /R/uploadPentadsToEE.R: -------------------------------------------------------------------------------- 1 | #' Upload pentads to Google Earth Engine server 2 | #' 3 | #' @param pentads An \href{https://github.com/r-spatial/sf}{sf} object with the pentads to upload 4 | #' @param asset_id A character string with the name we want our pentads to be 5 | #' saved on the server with. 6 | #' @param load If TRUE (default), the GEE asset is loaded into the R session. 7 | #' @param max_p Maximum number of pentads the function will try to upload 8 | #' without splitting into pieces. The default is a sensible choice but you can 9 | #' try modify it to serve your purposes. 10 | #' 11 | #' @return Pentads are uploaded to GEE. In addition a GEE feature collection can 12 | #' be loaded into the R environment 13 | #' @details An \href{https://github.com/r-spatial/sf}{sf} object is uploaded to GEE servers via 14 | #' "getInfo_to_asset" (see \link[rgee]{sf_as_ee}). If there are many pentads, 15 | #' the function will upload to objects and merge them in the server under the 16 | #' name provided. Please be conscious that two intermediate objects will also 17 | #' be stored under names "p1" and "p2". We recommend visiting your account and 18 | #' cleaning unnecesary objects regularly. 19 | #' @export 20 | #' 21 | #' @examples 22 | #' \dontrun{ 23 | #' # Load ABAP pentads 24 | #' pentads <- getRegionPentads(.region_type = "province", .region = "North West") 25 | #' 26 | #' # Set an ID for your remote asset (data in GEE) 27 | #' assetId <- sprintf("%s/%s", ee_get_assethome(), 'pentads') 28 | #' 29 | #' # Upload to GEE (if not done already - do this only once per asset) 30 | #' uploadPentadsToEE(pentads = pentads, 31 | #' asset_id = assetId, 32 | #' load = FALSE) 33 | #' 34 | #' # Load the remote asset to you local computer to work with it 35 | #' ee_pentads <- ee$FeatureCollection(assetId) 36 | #' 37 | #' # Alternatively we can upload to GEE and load the asset in one call 38 | #' ee_pentads <- uploadPentadsToEE(pentads = pentads, 39 | #' asset_id = assetId, 40 | #' load = TRUE) 41 | #' } 42 | uploadPentadsToEE <- function(pentads, asset_id, load = TRUE, max_p = 16250){ 43 | 44 | lifecycle::deprecate_warn( 45 | when = "0.3.0", 46 | what = "ABAP::uploadPentadsToEE()", 47 | with = "ABDtools::uploadFeaturesToEE()", 48 | details = "ABAP::uploadPentadsToEE() is replaced by ABDtools::uploadFeaturesToEE() from package ABDtools (https://github.com/AfricaBirdData/ABDtools). 49 | The ABAP function has been discontinued", 50 | id = NULL, 51 | always = FALSE, 52 | env = rlang::caller_env(), 53 | user_env = rlang::caller_env(2) 54 | ) 55 | 56 | message("This function has been discontinued. Please, use ABDtools::uploadFeaturesToEE() instead") 57 | message("(https://github.com/AfricaBirdData/ABDtools)") 58 | 59 | } 60 | -------------------------------------------------------------------------------- /man/addVarEEclosestImage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addVarEEclosestImage.R 3 | \name{addVarEEclosestImage} 4 | \alias{addVarEEclosestImage} 5 | \title{Add variable from closest image ina Google Earth Engine Collection} 6 | \usage{ 7 | addVarEEclosestImage( 8 | ee_pentads, 9 | collection, 10 | reducer, 11 | maxdiff, 12 | bands = NULL, 13 | unmask = FALSE 14 | ) 15 | } 16 | \arguments{ 17 | \item{ee_pentads}{A feature collection with the pentads we want to annotate. 18 | We need to upload an sf object with the pentads to GEE. This object must 19 | also have character column with the dates that need to be matched against the 20 | image collection dates. The format must be "yyyy-mm-dd" and the column must 21 | be named "Date".} 22 | 23 | \item{collection}{Either a character string with the name of the collection 24 | we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 25 | See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}.} 26 | 27 | \item{reducer}{A character string specifying the function apply when 28 | extracting values for each pentad. It is common to use "mean", "sum" or 29 | "count". But there are many other, see 'ee.Reducer' under Client Libraries at 30 | \url{https://developers.google.com/earth-engine/apidocs}.} 31 | 32 | \item{maxdiff}{Maximum difference in days allowed for an image to be matched with 33 | data.} 34 | 35 | \item{bands}{Select specific bands from the image. Only one band at a time is 36 | allowed for now.} 37 | 38 | \item{unmask}{GEE masks missing values, which means they are not used for 39 | computing means, counts, etc. Sometimes we might want to avoid this behaviour 40 | and use 0 instead of NA. If so, set unmask to TRUE.} 41 | } 42 | \value{ 43 | A dataframe similar to \code{ee_pentads} with variables added from the 44 | \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 45 | the name of the new variables will be the selected band (\code{bands} or else 46 | all bands from \code{collection} followed by the spatial reducer \code{reducer}. 47 | } 48 | \description{ 49 | Each feature in a feature collection (i.e. row in asimple feature 50 | collection) is matched with the image in an image collection that is closest 51 | to it in time. 52 | } 53 | \examples{ 54 | \dontrun{ 55 | # Load the remote data asset 56 | ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 57 | 58 | # Annotate with TerraClimate dataset 59 | visit_new <- addVarEEclosestImage(ee_pentads = ee_data, 60 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 61 | reducer = "mean", # We only need spatial reducer 62 | maxdiff = 15, # This is the maximum time difference that GEE checks 63 | bands = c("tmmn")) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /man/EEcollectionToMultiband.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/EEcollectionToMultiband.R 3 | \name{EEcollectionToMultiband} 4 | \alias{EEcollectionToMultiband} 5 | \title{Convert a GEE collection to multiband image} 6 | \usage{ 7 | EEcollectionToMultiband( 8 | collection, 9 | dates, 10 | band, 11 | group_type, 12 | groups, 13 | reducer = NULL, 14 | unmask = FALSE 15 | ) 16 | } 17 | \arguments{ 18 | \item{collection}{Either a character string with the name of the collection 19 | we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 20 | See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}.} 21 | 22 | \item{dates}{A character vector with two elements c(start, end). Format must be 23 | "yyyy-mm-dd".} 24 | 25 | \item{band}{Select a specific band from the collection. Only one band from 26 | the collection can be processed at a time.} 27 | 28 | \item{group_type}{The type of grouping we want to perform. This has to be a 29 | temporal grouping, either: 'day', 'week', 'month', or 'year'.} 30 | 31 | \item{groups}{An integer vector with values for the group. e.g. 32 | \code{2008:2019} will group data into years from 2008 to 2019.} 33 | 34 | \item{reducer}{The summarizing function applied to each group. If reducer is 35 | NULL, then the collection is transformed into a multiband image without 36 | applying any reduction (each image goes to a band).} 37 | 38 | \item{unmask}{GEE masks missing values, which means they are not used for 39 | computing means, counts, etc. Sometimes we might want to avoid this behaviour 40 | and use 0 instead of NA. If so, set unmask to TRUE.} 41 | } 42 | \value{ 43 | This function transforms an image collection made of a number of images, 44 | each representing a variable at different times (e.g. NDVI measures in different 45 | months) into a multiband image. Each band in the new image represent a different 46 | time. The advantage of a multiband image over an image collection is that we can 47 | annotate data with all the bands of an image on a single function call, saving 48 | time and data traffic between our machine and GEE servers. 49 | } 50 | \description{ 51 | Convert a GEE collection to multiband image 52 | } 53 | \examples{ 54 | \dontrun{ 55 | # Create a multi-band image with mean NDVI for each year 56 | multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 57 | dates = c("2008-01-01", "2020-01-01"), 58 | band = "NDVI", # You can find what bands are available from GEE catalog 59 | group_type = "year", 60 | groups = 2008:2019, 61 | reducer = "mean", 62 | unmask = FALSE) 63 | 64 | Find mean (mean) NDVI for each pentad and year 65 | ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 66 | pentads_ndvi <- addVarEEimage(ee_data, multiband, "mean") 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /man/getAbapData.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getAbapData.R 3 | \name{getAbapData} 4 | \alias{getAbapData} 5 | \title{Download data from ABAP cards for a region and species} 6 | \usage{ 7 | getAbapData( 8 | .spp_code, 9 | .region_type = c("country", "province", "pentad", "group"), 10 | .region, 11 | .years = NULL, 12 | .adhoc = FALSE 13 | ) 14 | } 15 | \arguments{ 16 | \item{.spp_code}{Character string or integer corresponding to the SAFRING 17 | code of the species of interest. See searchAbapSpecies.} 18 | 19 | \item{.region_type}{The type of region we are interested on. Four options: 20 | "country", "province", "pentad" and "group". See details.} 21 | 22 | \item{.region}{A character string corresponding to the specific region we are 23 | interested in. It can be either a country in Southern Africa, a South 24 | African province or a pentad code.} 25 | 26 | \item{.years}{A numeric vector with elements corresponding to the years we 27 | want data for.} 28 | 29 | \item{.adhoc}{If TRUE, \strong{only} ad-hoc lists are returned. If FALSE 30 | (default), no ad-hoc lists are returned.} 31 | } 32 | \value{ 33 | A tibble in which each row corresponds to one ABAP card. The column 34 | 'Spp' gives either the code of the species of interest, if it was detected 35 | in that card, or "-" if it wasn't. See \code{\link{abap_visit_vars}} for more 36 | information about the columns. 37 | } 38 | \description{ 39 | Download data from ABAP cards for a region and species 40 | } 41 | \details{ 42 | At the moment, ABAP serves data from eleven countries: South Africa, 43 | Botswana, eSwatini, Lesotho, Malawi, Mozambique, Namibia, Zambia, Zimbabwe, 44 | Kenya and Nigeria. Only South African provinces are available: Western Cape, 45 | Eastern Cape, Northern Cape, Free State, Limpopo, Mpumalanga, KwaZulu-Natal, 46 | Gauteng, and Northwest Province. 47 | 48 | If we specify "group" in the \code{.region} argument the 49 | function returns all records for a specific group of pentads. Groups of 50 | pentads must be created from the birdmap.africa websites (e.g., 51 | \href{https://sabap2.birdmap.africa/}{SABAP2} or 52 | \href{https://kenya.birdmap.africa/}{Kenya Bird Map}). You will need to 53 | create an account. Once logged in, you can create groups from the \code{coverage} 54 | menu. Then, these groups can be viewed from you home menu. The name of the 55 | group is the last part of the URL displayed in the browser's navigation bar. 56 | For example, I created a group named "test_group", and the URL for this group 57 | is \verb{https://kenya.birdmap.africa/coverage/group/xxxx_tst_grp}. The group name 58 | that we need to pass on to the \code{getAbapData()} function is \code{xxxx_tst_grp}, 59 | the last part of the URL, where \code{xxxx} is your citizen scientist number 60 | (provided when creating an account). 61 | } 62 | \examples{ 63 | getAbapData(123, .region_type = "country", .region = "South Africa") 64 | getAbapData(169, .region_type = "province", .region = "Eastern Cape", .years = 2008) 65 | getAbapData(95, .region_type = "pentad", .region = "2505_2850", .years = c(2008, 2009)) 66 | } 67 | -------------------------------------------------------------------------------- /man/addVarEEcollection.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addVarEEcollection.R 3 | \name{addVarEEcollection} 4 | \alias{addVarEEcollection} 5 | \title{Add variable from Google Earth Engine Collection} 6 | \usage{ 7 | addVarEEcollection( 8 | ee_pentads, 9 | collection, 10 | dates, 11 | temp_reducer, 12 | spt_reducer, 13 | bands = NULL, 14 | unmask = FALSE 15 | ) 16 | } 17 | \arguments{ 18 | \item{ee_pentads}{A feature collection with the pentads we want to annotate. 19 | We need to upload an sf object with the pentads to GEE.} 20 | 21 | \item{collection}{Either a character string with the name of the collection 22 | we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 23 | See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}.} 24 | 25 | \item{dates}{A character vector with two elements c(start, end). Format must be 26 | "yyyy-mm-dd".} 27 | 28 | \item{temp_reducer}{A character string specifying the function to summarize 29 | collection across time. It is common to use "mean", "sum" or "count", but 30 | there are many others, see 'ee.Reducer' under Client Libraries at 31 | \url{https://developers.google.com/earth-engine/apidocs}.} 32 | 33 | \item{spt_reducer}{A character string specifying the function apply when 34 | extracting values for each pentad. It is common to use "mean", "sum" or 35 | "count", but there are many others, see 'ee.Reducer' under Client Libraries at 36 | \url{https://developers.google.com/earth-engine/apidocs}.} 37 | 38 | \item{bands}{Select specific bands from the image. If not specified, pentads 39 | will be annotated with all bands (one column for each band).} 40 | 41 | \item{unmask}{GEE masks missing values, which means they are not used for 42 | computing means, counts, etc. Sometimes we might want to avoid this behaviour 43 | and use 0 instead of NA. If so, set unmask to TRUE.} 44 | } 45 | \value{ 46 | A dataframe similar to \code{ee_pentads} with variables added from the 47 | \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 48 | the name of the new variables will be the selected band (\code{bands} or else 49 | all bands from \code{collection} followed by the spatial reducer \code{spt_reducer}. 50 | The temporal reducer \code{temp_reducer} does not appear in the 51 | name, and therefore, it is up to the user to keep track of how the temporal 52 | reducer summarized the collection. 53 | } 54 | \description{ 55 | Add variable from Google Earth Engine Collection 56 | } 57 | \examples{ 58 | \dontrun{ 59 | # Load the remote data asset 60 | ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 61 | 62 | # Annotate with TerraClimate dataset 63 | pentads_tmmn <- addVarEEcollection(ee_pentads = ee_data, 64 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 65 | dates = c("2010-01-01", "2011-01-01"), 66 | temp_reducer = "mean", 67 | spt_reducer = "mean", 68 | bands = "tmmn") 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /man/abapToUnmarked_multi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abapToUnmarked_multi.R 3 | \name{abapToUnmarked_multi} 4 | \alias{abapToUnmarked_multi} 5 | \title{ABAP to unmarked (multi-season)} 6 | \usage{ 7 | abapToUnmarked_multi(abap_data, pentads = NULL) 8 | } 9 | \arguments{ 10 | \item{abap_data}{multi-season ABAP data downloaded using \code{\link{getAbapData}}.} 11 | 12 | \item{pentads}{an \code{sf} object returned by \code{\link{getRegionPentads}}. 13 | Defaults to \code{NULL}.} 14 | } 15 | \value{ 16 | an object of class \code{\link[unmarked]{unmarkedMultFrame}} 17 | } 18 | \description{ 19 | This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 20 | into an \code{\link[unmarked]{unmarkedMultFrame}} object which can be used to 21 | fit dynamic occupancy models using \code{\link[unmarked]{colext}} (MacKenzie et. al 2003) 22 | and \code{\link[ubms]{stan_colext}} from the \code{ubms} package (which fits 23 | Unmarked Bayesian Models with Stan). 24 | } 25 | \details{ 26 | In addition to reformatting the detection/non-detection ABAP data for 27 | use in \code{unmarked} and \code{ubms} occupancy models, this function also extracts two 28 | survey-level covariates: \code{hours} and \code{jday}. The \code{hours} variable is the total 29 | number of hours spent atlassing which is recorded on the pentad card and \code{jday} 30 | is the Julian day corresponding to the first day of atlassing for that card.\cr 31 | 32 | The function also adds the sampling year as a \code{yearlySiteCovs} which allows 33 | year to be used in the formula for colonization, extinction and detection 34 | probability.\cr 35 | 36 | If \code{pentads} are provided the \code{unmarked} frame will add the X and Y coordinates 37 | as site-level covariates (\code{siteCovs}). 38 | } 39 | \note{ 40 | The processing time of \code{abapToUnmarked_multi} can be considerably long 41 | if the number of cards and pentads of the focal species is high, so patience 42 | may be required. 43 | } 44 | \examples{ 45 | \dontrun{ 46 | library(unmarked) 47 | abap_multi <- getAbapData(.spp = 212, 48 | .region_type = "province", 49 | .region = "Eastern Cape", 50 | .years = c(2009,2010,2011,2012)) 51 | 52 | abap_pentads <- getRegionPentads(.region_type = "province", 53 | .region = "Eastern Cape") 54 | 55 | ## Return unmarked frame no site covariates 56 | um_df <- abapToUnmarked_multi(abap_multi) 57 | summary(um_df) 58 | 59 | ## Return unmarked frame with Pentad coordinates as site covariates 60 | um_df <- abapToUnmarked_multi(abap_data = abap_multi, pentads = abap_pentads) 61 | summary(um_df) 62 | } 63 | } 64 | \references{ 65 | MacKenzie, D. I., J. D. Nichols, J. E. Hines, M. G. Knutson, and A. B. 66 | Franklin. 2003. Estimating site occupancy, colonization, and local extinction 67 | when a species is detected imperfectly. Ecology 84:2200-2207. 68 | } 69 | \seealso{ 70 | \code{\link[unmarked]{colext}}, \code{\link[ubms]{stan_colext}} 71 | } 72 | \author{ 73 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 74 | Pachi Cervantes 75 | } 76 | -------------------------------------------------------------------------------- /R/addVarEEclosestImage.R: -------------------------------------------------------------------------------- 1 | #' Add variable from closest image ina Google Earth Engine Collection 2 | #' 3 | #' @description Each feature in a feature collection (i.e. row in asimple feature 4 | #' collection) is matched with the image in an image collection that is closest 5 | #' to it in time. 6 | #' @param ee_pentads A feature collection with the pentads we want to annotate. 7 | #' We need to upload an sf object with the pentads to GEE. This object must 8 | #' also have character column with the dates that need to be matched against the 9 | #' image collection dates. The format must be "yyyy-mm-dd" and the column must 10 | #' be named "Date". 11 | #' @param collection Either a character string with the name of the collection 12 | #' we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 13 | #' See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}. 14 | #' @param reducer A character string specifying the function apply when 15 | #' extracting values for each pentad. It is common to use "mean", "sum" or 16 | #' "count". But there are many other, see 'ee.Reducer' under Client Libraries at 17 | #' \url{https://developers.google.com/earth-engine/apidocs}. 18 | #' @param maxdiff Maximum difference in days allowed for an image to be matched with 19 | #' data. 20 | #' @param bands Select specific bands from the image. Only one band at a time is 21 | #' allowed for now. 22 | #' @param unmask GEE masks missing values, which means they are not used for 23 | #' computing means, counts, etc. Sometimes we might want to avoid this behaviour 24 | #' and use 0 instead of NA. If so, set unmask to TRUE. 25 | #' 26 | #' @return A dataframe similar to \code{ee_pentads} with variables added from the 27 | #' \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 28 | #' the name of the new variables will be the selected band (\code{bands} or else 29 | #' all bands from \code{collection} followed by the spatial reducer \code{reducer}. 30 | #' @export 31 | #' 32 | #' @examples 33 | #' \dontrun{ 34 | #' # Load the remote data asset 35 | #' ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 36 | #' 37 | #' # Annotate with TerraClimate dataset 38 | #' visit_new <- addVarEEclosestImage(ee_pentads = ee_data, 39 | #' collection = "IDAHO_EPSCOR/TERRACLIMATE", 40 | #' reducer = "mean", # We only need spatial reducer 41 | #' maxdiff = 15, # This is the maximum time difference that GEE checks 42 | #' bands = c("tmmn")) 43 | #' } 44 | addVarEEclosestImage <- function(ee_pentads, collection, reducer, maxdiff, 45 | bands = NULL, unmask = FALSE){ 46 | 47 | lifecycle::deprecate_warn( 48 | when = "0.3.0", 49 | what = "ABAP::addVarEEclosestImage()", 50 | with = "ABDtools::addVarEEclosestImage()", 51 | details = "A new version of addVarEEclosestImage() is now on package ABDtools (https://github.com/AfricaBirdData/ABDtools). 52 | The ABAP function has been discontinued", 53 | id = NULL, 54 | always = FALSE, 55 | env = rlang::caller_env(), 56 | user_env = rlang::caller_env(2) 57 | ) 58 | 59 | message("This function has been discontinued. Please, use ABDtools::addVarEEclosestImage() instead") 60 | message("(https://github.com/AfricaBirdData/ABDtools)") 61 | 62 | } 63 | -------------------------------------------------------------------------------- /R/EEcollectionToMultiband.R: -------------------------------------------------------------------------------- 1 | #' Convert a GEE collection to multiband image 2 | #' 3 | #' @param collection Either a character string with the name of the collection 4 | #' we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 5 | #' See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}. 6 | #' @param dates A character vector with two elements c(start, end). Format must be 7 | #' "yyyy-mm-dd". 8 | #' @param band Select a specific band from the collection. Only one band from 9 | #' the collection can be processed at a time. 10 | #' @param group_type The type of grouping we want to perform. This has to be a 11 | #' temporal grouping, either: 'day', 'week', 'month', or 'year'. 12 | #' @param groups An integer vector with values for the group. e.g. 13 | #' \code{2008:2019} will group data into years from 2008 to 2019. 14 | #' @param reducer The summarizing function applied to each group. If reducer is 15 | #' NULL, then the collection is transformed into a multiband image without 16 | #' applying any reduction (each image goes to a band). 17 | #' @param unmask GEE masks missing values, which means they are not used for 18 | #' computing means, counts, etc. Sometimes we might want to avoid this behaviour 19 | #' and use 0 instead of NA. If so, set unmask to TRUE. 20 | #' 21 | #' @return This function transforms an image collection made of a number of images, 22 | #' each representing a variable at different times (e.g. NDVI measures in different 23 | #' months) into a multiband image. Each band in the new image represent a different 24 | #' time. The advantage of a multiband image over an image collection is that we can 25 | #' annotate data with all the bands of an image on a single function call, saving 26 | #' time and data traffic between our machine and GEE servers. 27 | #' @export 28 | #' 29 | #' @examples 30 | #' \dontrun{ 31 | #' # Create a multi-band image with mean NDVI for each year 32 | #' multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 33 | #' dates = c("2008-01-01", "2020-01-01"), 34 | #' band = "NDVI", # You can find what bands are available from GEE catalog 35 | #' group_type = "year", 36 | #' groups = 2008:2019, 37 | #' reducer = "mean", 38 | #' unmask = FALSE) 39 | #' 40 | #' Find mean (mean) NDVI for each pentad and year 41 | #' ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 42 | #' pentads_ndvi <- addVarEEimage(ee_data, multiband, "mean") 43 | #' 44 | #' } 45 | EEcollectionToMultiband <- function(collection, dates, band, 46 | group_type, groups, 47 | reducer = NULL, 48 | unmask = FALSE){ 49 | 50 | lifecycle::deprecate_warn( 51 | when = "0.3.0", 52 | what = "ABAP::EEcollectionToMultiband()", 53 | with = "ABDtools::EEcollectionToMultiband()", 54 | details = "A new version of EEcollectionToMultiband() is now on package ABDtools (https://github.com/AfricaBirdData/ABDtools). 55 | The ABAP function has been discontinued", 56 | id = NULL, 57 | always = FALSE, 58 | env = rlang::caller_env(), 59 | user_env = rlang::caller_env(2) 60 | ) 61 | 62 | message("This function has been discontinued. Please, use ABDtools::EEcollectionToMultiband() instead") 63 | message("(https://github.com/AfricaBirdData/ABDtools)") 64 | 65 | } 66 | -------------------------------------------------------------------------------- /man/abapToUnmarked_single.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abapToUnmarked_single.R 3 | \name{abapToUnmarked_single} 4 | \alias{abapToUnmarked_single} 5 | \title{ABAP to unmarked (single-season)} 6 | \usage{ 7 | abapToUnmarked_single(abap_data, pentads = NULL) 8 | } 9 | \arguments{ 10 | \item{abap_data}{single-season ABAP data downloaded using \code{\link{getAbapData}}} 11 | 12 | \item{pentads}{an \code{sf} object returned by \code{\link{getRegionPentads}}. 13 | Defaults to \code{NULL}.} 14 | } 15 | \value{ 16 | an object of class \code{\link[unmarked]{unmarkedFrameOccu}} 17 | } 18 | \description{ 19 | This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 20 | into an \code{\link[unmarked]{unmarkedFrameOccu}} object which can be used to 21 | fit single-season occupancy models using \code{\link[unmarked]{occu}} (MacKenzie et. al 2002) 22 | or \code{\link[unmarked]{occuRN}} (Royle and Nichols, 2003) in \code{unmarked}. 23 | 24 | \code{\link[unmarked]{unmarkedFrameOccu}} objects can also be used to fit \code{\link[ubms]{stan_occu}} 25 | or \code{\link[ubms]{stan_occuRN}} models from the \code{ubms} package (which fits 26 | Unmarked Bayesian Models with Stan). 27 | } 28 | \details{ 29 | In addition to reformatting the detection/non-detection ABAP data 30 | for use in \code{unmarked} and \code{ubms} occupancy models, this function also extracts 31 | two survey-level covariates: \code{ hours} and \code{jday}. The \code{hours} variable is the 32 | total number of hours spent atlassing which is recorded on the pentad card and 33 | \code{jday} is the Julian day corresponding to the first day of atlassing for that 34 | card. If \code{pentads} are provided the \code{unmarked} frame will add the x and y 35 | coordinates as site covariates (\code{siteCovs}). The spatial data can be used as 36 | random effects to run a restricted spatial regression (RSR) occupancy model 37 | in \code{ubms}. See \code{\link[ubms]{RSR}} for more details. 38 | } 39 | \note{ 40 | It's important to make sure that the \code{.region_type} and \code{.region} are 41 | the same when extracting \code{abap_data} and \code{pentads} (see example below). The 42 | processing time of \code{abapToUnmarked_single} can be considerably long if the 43 | number of cards and pentads of the focal species is high, so patience may be 44 | required. 45 | } 46 | \examples{ 47 | \dontrun{ 48 | abap_single <- getAbapData(.spp_code = 212, 49 | .region_type = "province", 50 | .region = "Eastern Cape", 51 | .years = 2012) 52 | 53 | abap_pentads <- getRegionPentads(.region_type = "province", 54 | .region = "Eastern Cape") 55 | 56 | ## Return unmarked frame no site covariates 57 | um_df <- abapToUnmarked_single(abap_single) 58 | 59 | ## Return unmarked frame with Pentad coordinates as site covariates 60 | um_df <- abapToUnmarked_single(abap_single, abap_pentads) 61 | } 62 | } 63 | \references{ 64 | MacKenzie, D. I., J. D. Nichols, G. B. Lachman, S. Droege, J. Andrew Royle, 65 | and C. A. Langtimm. 2002. Estimating Site Occupancy Rates When Detection 66 | Probabilities Are Less Than One. Ecology 83: 2248-2255. 67 | 68 | Royle, J. A. and Nichols, J. D. (2003) Estimating Abundance from Repeated 69 | Presence-Absence 70 | Data or Point Counts. Ecology, 84(3) pp. 777-790. 71 | } 72 | \seealso{ 73 | \code{\link[unmarked]{occu}}, \code{\link[unmarked]{occuRN}}, 74 | \code{\link[ubms]{stan_occu}}, \code{\link[ubms]{stan_occuRN}} 75 | } 76 | \author{ 77 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 78 | Pachi Cervantes 79 | } 80 | -------------------------------------------------------------------------------- /R/addVarEEcollection.R: -------------------------------------------------------------------------------- 1 | #' Add variable from Google Earth Engine Collection 2 | #' 3 | #' @param ee_pentads A feature collection with the pentads we want to annotate. 4 | #' We need to upload an sf object with the pentads to GEE. 5 | #' @param collection Either a character string with the name of the collection 6 | #' we want to use or a GEE collection produced with \code{ee$ImageCollection()}. 7 | #' See \href{https://developers.google.com/earth-engine/datasets/catalog}{GEE catalog}. 8 | #' @param dates A character vector with two elements c(start, end). Format must be 9 | #' "yyyy-mm-dd". 10 | #' @param temp_reducer A character string specifying the function to summarize 11 | #' collection across time. It is common to use "mean", "sum" or "count", but 12 | #' there are many others, see 'ee.Reducer' under Client Libraries at 13 | #' \url{https://developers.google.com/earth-engine/apidocs}. 14 | #' @param spt_reducer A character string specifying the function apply when 15 | #' extracting values for each pentad. It is common to use "mean", "sum" or 16 | #' "count", but there are many others, see 'ee.Reducer' under Client Libraries at 17 | #' \url{https://developers.google.com/earth-engine/apidocs}. 18 | #' @param bands Select specific bands from the image. If not specified, pentads 19 | #' will be annotated with all bands (one column for each band). 20 | #' @param unmask GEE masks missing values, which means they are not used for 21 | #' computing means, counts, etc. Sometimes we might want to avoid this behaviour 22 | #' and use 0 instead of NA. If so, set unmask to TRUE. 23 | #' 24 | #' @return A dataframe similar to \code{ee_pentads} with variables added from the 25 | #' \code{bands} selected from \code{collection}. Note that following \href{https://github.com/r-spatial/rgee}{rgee} 26 | #' the name of the new variables will be the selected band (\code{bands} or else 27 | #' all bands from \code{collection} followed by the spatial reducer \code{spt_reducer}. 28 | #' The temporal reducer \code{temp_reducer} does not appear in the 29 | #' name, and therefore, it is up to the user to keep track of how the temporal 30 | #' reducer summarized the collection. 31 | #' @export 32 | #' 33 | #' @examples 34 | #' \dontrun{ 35 | #' # Load the remote data asset 36 | #' ee_data <- ee$FeatureCollection(assetId) # assetId must correspond to an asset in your GEE account 37 | #' 38 | #'# Annotate with TerraClimate dataset 39 | #' pentads_tmmn <- addVarEEcollection(ee_pentads = ee_data, 40 | #' collection = "IDAHO_EPSCOR/TERRACLIMATE", 41 | #' dates = c("2010-01-01", "2011-01-01"), 42 | #' temp_reducer = "mean", 43 | #' spt_reducer = "mean", 44 | #' bands = "tmmn") 45 | #' } 46 | addVarEEcollection <- function(ee_pentads, collection, dates, 47 | temp_reducer, spt_reducer, 48 | bands = NULL, unmask = FALSE){ 49 | 50 | lifecycle::deprecate_warn( 51 | when = "0.3.0", 52 | what = "ABAP::addVarEEcollection()", 53 | with = "ABDtools::addVarEEcollection()", 54 | details = "A new version of addVarEEcollection() is now on package ABDtools (https://github.com/AfricaBirdData/ABDtools). 55 | The ABAP function has been discontinued", 56 | id = NULL, 57 | always = FALSE, 58 | env = rlang::caller_env(), 59 | user_env = rlang::caller_env(2) 60 | ) 61 | 62 | message("This function has been discontinued. Please, use ABDtools::addVarEEcollection() instead") 63 | message("(https://github.com/AfricaBirdData/ABDtools)") 64 | } 65 | -------------------------------------------------------------------------------- /man/abapToSpOcc_single.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abapToSpOcc_single.R 3 | \name{abapToSpOcc_single} 4 | \alias{abapToSpOcc_single} 5 | \title{ABAP to spOccupancy (single-species)} 6 | \usage{ 7 | abapToSpOcc_single(abap_data, pentads = NULL, proj_coords = TRUE) 8 | } 9 | \arguments{ 10 | \item{abap_data}{single-season ABAP data downloaded using \code{\link{getAbapData}}.} 11 | 12 | \item{pentads}{an \code{sf} object returned by \code{\link{getRegionPentads}}. Defaults to \code{NULL}.} 13 | 14 | \item{proj_coords}{logical value indicating whether pentad coordinates are 15 | projected (\code{TRUE}) or kept in decimal degree format (\code{FALSE}). Defaults to \code{TRUE}. 16 | See details below for coordinate reference system used during transformation.} 17 | } 18 | \value{ 19 | A list containing data necessary for model fitting in \code{spOccupancy}. 20 | List elements are \code{y} (detection/non-detection data), \code{det.covs} (survey-level covariates), 21 | and \code{coords} (x and y centroids of pentads if spatial data are supplied). 22 | } 23 | \description{ 24 | This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 25 | into an list which can be used to fit single-species occupancy models using 26 | \code{\link[spOccupancy]{spPGOcc}} (spatial) or \code{\link[spOccupancy]{PGOcc}} 27 | (non-spatial). The \code{spOccupancy} package fits single-species, multi-species, 28 | and integrated non-spatial and spatial occupancy models using Markov Chain Monte Carlo (MCMC). 29 | } 30 | \details{ 31 | The \code{\link[spOccupancy]{spPGOcc}} function takes \code{coords} as an 32 | argument with X and Y coordinates included for each site. Within the context 33 | of ABAP, these \code{coords} are the centroid of each sampling pentad. In order to 34 | provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 35 | and provide the same inputs for \code{.region_type} and \code{.region} that are specified 36 | in corresponding \code{\link{getAbapData}} call. If proj_coords is set to \code{TRUE} 37 | then the coordinates will be transformed using the African Albers Equal Area 38 | coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 39 | for details). This projection is best suited for land masses extending in an 40 | east-to-west orientation at mid-latitudes making it suitable for projecting 41 | pentads in Southern Africa. The functions in the \code{spOccupancy} package assume 42 | that coordinates are projected so for best results it is recommended to always 43 | project the data. \cr 44 | 45 | If \code{pentads} are specified then the output can be automatically used in 46 | \code{\link[spOccupancy]{spPGOcc}}. If no spatial data are provided the output 47 | can be used in \code{\link[spOccupancy]{PGOcc}}.\cr 48 | 49 | In addition to reformatting the detection/non-detection ABAP data for use in 50 | \code{spOccupancy} occupancy models, this function also extracts two survey-level 51 | covariates and adds them to the output list: \code{ hours} and \code{jday}. The \code{hours} 52 | variable is the total number of hours spent atlassing which is recorded on the 53 | pentad card and \code{jday} is the Julian day corresponding to the first day of 54 | atlassing for that card. 55 | } 56 | \note{ 57 | The processing time of \code{abapToSpOcc_single} can be considerably long if 58 | the number of cards and pentads of the focal species is high, so patience may 59 | be required. 60 | } 61 | \examples{ 62 | abap_data <- getAbapData(.spp_code = 212, 63 | .region_type = "province", 64 | .region = "Eastern Cape", 65 | .years = 2012) 66 | 67 | abap_pentads <- getRegionPentads(.region_type = "province", 68 | .region = "Eastern Cape") 69 | 70 | 71 | ## Return list for spatial occupancy model 72 | spOcc <- abapToSpOcc_single(abap_data, abap_pentads) 73 | str(spOcc) 74 | 75 | ## Return list for spatial occupancy model (without coordinate projection) 76 | spOcc <- abapToSpOcc_single(abap_data, abap_pentads, proj_coords = FALSE) 77 | str(spOcc) 78 | 79 | ## List for non-spatial occupancy model 80 | spOcc <- abapToSpOcc_single(abap_data) 81 | str(spOcc) 82 | 83 | } 84 | \seealso{ 85 | \code{\link[spOccupancy]{spPGOcc}}, \code{\link[spOccupancy]{PGOcc}} 86 | } 87 | \author{ 88 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 89 | Pachi Cervantes 90 | } 91 | -------------------------------------------------------------------------------- /beta/getAbapData.R: -------------------------------------------------------------------------------- 1 | #' Download data from ABAP cards for a region and species 2 | #' 3 | #' @param .spp_code Character string or integer corresponding to the SAFRING code 4 | #' of the species of interest. See searchAbapSpecies. 5 | #' @param .region_type The type of region we are interested on. 6 | #' Three options: "country", "province" and "pentad". 7 | #' @param .region A character string corresponding to the specific region we are 8 | #' interested in. It can be either a country in Southern Africa, a South African 9 | #' province or a pentad code. 10 | #' @param .years A numeric vector with elements corresponding to the years we 11 | #' want data for. 12 | #' @param .adhoc If TRUE, **only** ad-hoc lists are returned. Defaults to FALSE. 13 | #' 14 | #' @return A tibble in which each row corresponds to one ABAP card. The column 15 | #' 'Spp' gives either the code of the species of interest, if it was detected 16 | #' in that card, or "-" if it wasn't. 17 | #' @export 18 | #' 19 | #' @examples 20 | #' getAbapData(123, .region_type = "country", .region = "South Africa") 21 | #' getAbapData(169, .region_type = "province", .region = "Eastern Cape", .years = 2008) 22 | #' getAbapData(95, .region_type = "pentad", .region = "2505_2850", .years = c(2008, 2009)) 23 | getAbapData <- function(.spp_code, 24 | .region_type = c("country", "province", "pentad"), 25 | .region, .years = NULL, .adhoc = FALSE){ 26 | 27 | if(is.null(.region_type)){ 28 | .region_type <- "country" 29 | } else if(!.region_type %in% c("country", "province", "pentad")){ 30 | stop(".region_type must be one of 'country', 'province', 'pentad'") 31 | } 32 | 33 | .region <- tolower(.region) 34 | .region <- gsub(" ", "", .region) 35 | 36 | # For multi-species queries, we will use a different API call 37 | # THE PROBLEM WITH THIS IS THAT MULTISPECIES QUERIES DON'T RETRIEVE CARDS WITHOUT ANY OF THE SPECIES (NON-DETECTION) 38 | if(length(.spp_code) > 1){ 39 | 40 | if(.region_type != "country"){ 41 | stop("Multi-species queries are supported only countries at the moment.") 42 | } 43 | 44 | date_start <- paste0(min(.years), "-01-01") 45 | date_end <- paste0(max(.years)+1, "-01-01") 46 | 47 | url <- paste0("https://api.birdmap.africa/sabap2/v2/R/", date_start, "/", date_end,"/country/", .region, "/data/species/", 48 | paste(.spp_code, collapse = ","), "?format=CSV") 49 | 50 | } else { 51 | 52 | if(!is.null(.years)){ 53 | .years <- paste(.years, collapse = ",") 54 | .years <- paste0("&year=", .years) 55 | } 56 | 57 | url <- paste0("https://api.birdmap.africa/sabap2/v2/cards/species/85ee37929696cba93e1cdda4dbb3f93a/", .spp_code, "/", 58 | .region_type, "/", .region, "?format=csv&inclnull=1", .years) 59 | } 60 | 61 | if(.adhoc){ 62 | url <- paste0(url, "&adhoc=1") 63 | } 64 | 65 | # Extract data 66 | myfile <- httr::RETRY("GET", url) %>% 67 | httr::content(as = "text", encoding = "UTF-8") 68 | 69 | if(myfile == ""){ 70 | stop("We couldn't retrieve your query. Please check your spelling and try again.") 71 | } 72 | 73 | # Format 74 | out <- myfile %>% 75 | textConnection() %>% 76 | utils::read.csv(header = TRUE) %>% 77 | dplyr::as_tibble() 78 | 79 | # If there are multiple regions (e.g. multiple pentads), then multiple headers 80 | # are produced and inserted as data. Eliminate these 81 | out <- out %>% 82 | dplyr::filter(Pentad != "Pentad") 83 | 84 | # Rename columns of multi-species queries 85 | if(length(.spp_code) > 1){ 86 | 87 | out <- out %>% 88 | dplyr::mutate(Common_name = paste0(Common_group, ", ", Common_species), 89 | Taxonomic_name = paste(Genus, Species)) %>% 90 | dplyr::select(-c("Common_group", "Common_species", "Genus", "Species")) 91 | 92 | } 93 | 94 | out <- out %>% 95 | readr::type_convert(col_types = readr::cols( 96 | .default = readr::col_integer(), 97 | CardNo = readr::col_character(), 98 | StartDate = readr::col_date(format = ""), 99 | EndDate = readr::col_date(format = ""), 100 | StartTime = readr::col_character(), 101 | Pentad = readr::col_character(), 102 | Spp = readr::col_character(), 103 | Sequence = readr::col_character(), 104 | Common_name = readr::col_character(), 105 | Taxonomic_name = readr::col_character())) 106 | 107 | return(out) 108 | } 109 | -------------------------------------------------------------------------------- /man/abapToSpOcc_multi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abapToSpOcc_multi.R 3 | \name{abapToSpOcc_multi} 4 | \alias{abapToSpOcc_multi} 5 | \title{ABAP to spOccupancy (multi-season)} 6 | \usage{ 7 | abapToSpOcc_multi( 8 | abap_data, 9 | pentads = NULL, 10 | proj_coords = TRUE, 11 | seasons = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{abap_data}{multi-season ABAP data downloaded using \code{\link{getAbapData}}.} 16 | 17 | \item{pentads}{an \code{sf} object returned by \code{\link{getRegionPentads}}. Defaults to \code{NULL}.} 18 | 19 | \item{proj_coords}{logical value indicating whether pentad coordinates are 20 | projected (\code{TRUE}) or kept in decimal degree format (\code{FALSE}). Defaults to \code{TRUE}. 21 | See details below for coordinate reference system used during transformation.} 22 | 23 | \item{seasons}{string indicating the name of the variable in \code{abap_data} that should 24 | be used to define seasons in multi-season models.} 25 | } 26 | \value{ 27 | A list containing data necessary for model fitting in \code{spOccupancy}. 28 | List elements are \code{y} (detection/non-detection data), \code{det.covs} (survey-level covariates), 29 | and \code{coords} (x and y centroids of pentads if spatial data are supplied). 30 | } 31 | \description{ 32 | This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 33 | into an list which can be used to fit single-species occupancy models using 34 | \code{\link[spOccupancy]{spPGOcc}} (spatial) or \code{\link[spOccupancy]{PGOcc}} 35 | (non-spatial). The \code{spOccupancy} package fits single-species, multi-species, 36 | and integrated non-spatial and spatial occupancy models using Markov Chain Monte Carlo (MCMC). 37 | } 38 | \details{ 39 | The \code{\link[spOccupancy]{spPGOcc}} function takes \code{coords} as an 40 | argument with X and Y coordinates included for each site. Within the context 41 | of ABAP, these \code{coords} are the centroid of each sampling pentad. In order to 42 | provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 43 | and provide the same inputs for \code{.region_type} and \code{.region} that are specified 44 | in corresponding \code{\link{getAbapData}} call. If proj_coords is set to \code{TRUE} 45 | then the coordinates will be transformed using the African Albers Equal Area 46 | coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 47 | for details). This projection is best suited for land masses extending in an 48 | east-to-west orientation at mid-latitudes making it suitable for projecting 49 | pentads in Southern Africa. The functions in the \code{spOccupancy} package assume 50 | that coordinates are projected so for best results it is recommended to always 51 | project the data. \cr 52 | 53 | If \code{pentads} are specified then the output can be automatically used in 54 | \code{\link[spOccupancy]{stPGOcc}}. If no spatial data are provided the output 55 | can be used in \code{\link[spOccupancy]{tPGOcc}}.\cr 56 | 57 | In addition to reformatting the detection/non-detection ABAP data for use in 58 | \code{spOccupancy} occupancy models, this function also extracts two survey-level 59 | covariates and adds them to the output list: \code{ hours} and \code{jday}. The \code{hours} 60 | variable is the total number of hours spent atlassing which is recorded on the 61 | pentad card and \code{jday} is the Julian day corresponding to the first day of 62 | atlassing for that card. 63 | } 64 | \examples{ 65 | abap_data <- getAbapData(.spp_code = 212, 66 | .region_type = "province", 67 | .region = "Eastern Cape", 68 | .years = 2012:2014) 69 | 70 | abap_pentads <- getRegionPentads(.region_type = "province", 71 | .region = "Eastern Cape") 72 | # We will use years as occupancy reference seasons 73 | abap_data$year <- format(abap_data$StartDate, "\%Y") 74 | 75 | ## Return list for spatial occupancy model 76 | stOcc <- abapToSpOcc_multi(abap_data, abap_pentads, seasons = "year") 77 | str(stOcc) 78 | 79 | ## Return list for spatial occupancy model (without coordinate projection) 80 | stOcc <- abapToSpOcc_multi(abap_data, abap_pentads, proj_coords = FALSE, "year") 81 | str(stOcc) 82 | 83 | ## List for non-spatial occupancy model 84 | tOcc <- abapToSpOcc_multi(abap_data, seasons = "year") 85 | str(tOcc) 86 | 87 | 88 | } 89 | \seealso{ 90 | \code{\link[spOccupancy]{stPGOcc}}, \code{\link[spOccupancy]{tPGOcc}} 91 | } 92 | \author{ 93 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 94 | Pachi Cervantes 95 | } 96 | -------------------------------------------------------------------------------- /R/getAbapData.R: -------------------------------------------------------------------------------- 1 | #' Download data from ABAP cards for a region and species 2 | #' 3 | #' @param .spp_code Character string or integer corresponding to the SAFRING 4 | #' code of the species of interest. See searchAbapSpecies. 5 | #' @param .region_type The type of region we are interested on. Four options: 6 | #' "country", "province", "pentad" and "group". See details. 7 | #' @param .region A character string corresponding to the specific region we are 8 | #' interested in. It can be either a country in Southern Africa, a South 9 | #' African province or a pentad code. 10 | #' @param .years A numeric vector with elements corresponding to the years we 11 | #' want data for. 12 | #' @param .adhoc If TRUE, **only** ad-hoc lists are returned. If FALSE 13 | #' (default), no ad-hoc lists are returned. 14 | #' 15 | #' @returns A tibble in which each row corresponds to one ABAP card. The column 16 | #' 'Spp' gives either the code of the species of interest, if it was detected 17 | #' in that card, or "-" if it wasn't. See \code{\link{abap_visit_vars}} for more 18 | #' information about the columns. 19 | #' 20 | #' @details At the moment, ABAP serves data from eleven countries: South Africa, 21 | #' Botswana, eSwatini, Lesotho, Malawi, Mozambique, Namibia, Zambia, Zimbabwe, 22 | #' Kenya and Nigeria. Only South African provinces are available: Western Cape, 23 | #' Eastern Cape, Northern Cape, Free State, Limpopo, Mpumalanga, KwaZulu-Natal, 24 | #' Gauteng, and Northwest Province. 25 | #' 26 | #' If we specify "group" in the `.region` argument the 27 | #' function returns all records for a specific group of pentads. Groups of 28 | #' pentads must be created from the birdmap.africa websites (e.g., 29 | #' \href{https://sabap2.birdmap.africa/}{SABAP2} or 30 | #' \href{https://kenya.birdmap.africa/}{Kenya Bird Map}). You will need to 31 | #' create an account. Once logged in, you can create groups from the `coverage` 32 | #' menu. Then, these groups can be viewed from you home menu. The name of the 33 | #' group is the last part of the URL displayed in the browser's navigation bar. 34 | #' For example, I created a group named "test_group", and the URL for this group 35 | #' is `https://kenya.birdmap.africa/coverage/group/xxxx_tst_grp`. The group name 36 | #' that we need to pass on to the `getAbapData()` function is `xxxx_tst_grp`, 37 | #' the last part of the URL, where `xxxx` is your citizen scientist number 38 | #' (provided when creating an account). 39 | #' 40 | #' @export 41 | #' 42 | #' @examples 43 | #' getAbapData(123, .region_type = "country", .region = "South Africa") 44 | #' getAbapData(169, .region_type = "province", .region = "Eastern Cape", .years = 2008) 45 | #' getAbapData(95, .region_type = "pentad", .region = "2505_2850", .years = c(2008, 2009)) 46 | getAbapData <- function(.spp_code, 47 | .region_type = c("country", "province", "pentad", "group"), 48 | .region, .years = NULL, .adhoc = FALSE){ 49 | 50 | .region_type <- match.arg(.region_type) 51 | 52 | if(!is.null(.years)){ 53 | .years <- paste(.years, collapse = ",") 54 | .years <- paste0("&year=", .years) 55 | } 56 | 57 | .region <- tolower(.region) 58 | .region <- gsub(" ", "", .region) 59 | 60 | url <- paste0("https://api.birdmap.africa/sabap2/v2/cards/species/85ee37929696cba93e1cdda4dbb3f93a/", .spp_code, "/", 61 | .region_type, "/", .region, "?format=csv&inclnull=1", .years) 62 | 63 | if(.adhoc){ 64 | url <- paste0(url, "&adhoc=1") 65 | } 66 | 67 | # Extract data 68 | myfile <- httr::RETRY("GET", url) %>% 69 | httr::content(as = "text", encoding = "UTF-8") 70 | 71 | if(myfile == ""){ 72 | stop("We couldn't retrieve your query. Please check your spelling and try again.") 73 | } 74 | 75 | # Format 76 | out <- myfile %>% 77 | textConnection() %>% 78 | utils::read.csv(header = TRUE) %>% 79 | dplyr::as_tibble() 80 | 81 | # If there are multiple regions (e.g. multiple pentads), then multiple headers 82 | # are produced and inserted as data. Eliminate these 83 | out <- out %>% 84 | dplyr::filter(Pentad != "Pentad") 85 | 86 | out <- out %>% 87 | readr::type_convert(col_types = readr::cols( 88 | .default = readr::col_integer(), 89 | CardNo = readr::col_character(), 90 | StartDate = readr::col_date(format = ""), 91 | EndDate = readr::col_date(format = ""), 92 | StartTime = readr::col_character(), 93 | Pentad = readr::col_character(), 94 | Spp = readr::col_character(), 95 | Sequence = readr::col_character(), 96 | Common_name = readr::col_character(), 97 | Taxonomic_name = readr::col_character())) 98 | 99 | return(out) 100 | } 101 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------- 2 | # CITATION file created with {cffr} R package, v0.2.1 3 | # See also: https://docs.ropensci.org/cffr/ 4 | # ----------------------------------------------------------- 5 | 6 | cff-version: 1.2.0 7 | message: 'To cite package "ABAP" in publications use:' 8 | type: software 9 | license: MIT 10 | title: 'ABAP: Access to African Bird Atlas Project data from R' 11 | version: 0.0.4 12 | abstract: This package provides functions to access the ABAP server API and download 13 | data. 14 | authors: 15 | - name: BIRDIE Development Team 16 | email: f.cervantesperalta@gmail.com 17 | orcid: https://orcid.org/YOUR-ORCID-ID 18 | preferred-citation: 19 | type: manual 20 | title: 'ABAP: Access to African Bird Atlas Project data from R' 21 | authors: 22 | - name: BIRDIE Development Team 23 | email: f.cervantesperalta@gmail.com 24 | orcid: https://orcid.org/YOUR-ORCID-ID 25 | version: 0.0.4 26 | abstract: This package provides functions to access the ABAP server API and download 27 | data. 28 | repository-code: https://github.com/AfricaBirdData/ABAP 29 | url: https://github.com/AfricaBirdData/ABAP 30 | contact: 31 | - name: BIRDIE Development Team 32 | email: f.cervantesperalta@gmail.com 33 | orcid: https://orcid.org/YOUR-ORCID-ID 34 | license: MIT 35 | year: '2022' 36 | repository-code: https://github.com/AfricaBirdData/ABAP 37 | url: https://github.com/AfricaBirdData/ABAP 38 | contact: 39 | - name: BIRDIE Development Team 40 | email: f.cervantesperalta@gmail.com 41 | orcid: https://orcid.org/YOUR-ORCID-ID 42 | references: 43 | - type: software 44 | title: data.table 45 | abstract: 'data.table: Extension of `data.frame`' 46 | notes: Imports 47 | authors: 48 | - family-names: Dowle 49 | given-names: Matt 50 | email: mattjdowle@gmail.com 51 | - family-names: Srinivasan 52 | given-names: Arun 53 | email: asrini@pm.me 54 | year: '2022' 55 | url: https://CRAN.R-project.org/package=data.table 56 | - type: software 57 | title: dplyr 58 | abstract: 'dplyr: A Grammar of Data Manipulation' 59 | notes: Imports 60 | authors: 61 | - family-names: Wickham 62 | given-names: Hadley 63 | email: hadley@rstudio.com 64 | orcid: https://orcid.org/0000-0003-4757-117X 65 | - family-names: François 66 | given-names: Romain 67 | orcid: https://orcid.org/0000-0002-2444-4226 68 | - family-names: Henry 69 | given-names: Lionel 70 | - family-names: Müller 71 | given-names: Kirill 72 | orcid: https://orcid.org/0000-0002-1416-3412 73 | year: '2022' 74 | url: https://CRAN.R-project.org/package=dplyr 75 | - type: software 76 | title: httr 77 | abstract: 'httr: Tools for Working with URLs and HTTP' 78 | notes: Imports 79 | authors: 80 | - family-names: Wickham 81 | given-names: Hadley 82 | email: hadley@rstudio.com 83 | year: '2022' 84 | url: https://CRAN.R-project.org/package=httr 85 | - type: software 86 | title: magrittr 87 | abstract: 'magrittr: A Forward-Pipe Operator for R' 88 | notes: Imports 89 | authors: 90 | - family-names: Bache 91 | given-names: Stefan Milton 92 | email: stefan@stefanbache.dk 93 | - family-names: Wickham 94 | given-names: Hadley 95 | email: hadley@rstudio.com 96 | year: '2022' 97 | url: https://CRAN.R-project.org/package=magrittr 98 | - type: software 99 | title: readr 100 | abstract: 'readr: Read Rectangular Text Data' 101 | notes: Imports 102 | authors: 103 | - family-names: Wickham 104 | given-names: Hadley 105 | email: hadley@rstudio.com 106 | - family-names: Hester 107 | given-names: Jim 108 | - family-names: Bryan 109 | given-names: Jennifer 110 | email: jenny@rstudio.com 111 | orcid: https://orcid.org/0000-0002-6983-2759 112 | year: '2022' 113 | url: https://CRAN.R-project.org/package=readr 114 | - type: software 115 | title: rgee 116 | abstract: 'rgee: R Bindings for Calling the ''Earth Engine'' API' 117 | notes: Imports 118 | authors: 119 | - family-names: Aybar 120 | given-names: Cesar 121 | email: csaybar@gmail.com 122 | orcid: https://orcid.org/0000-0003-2745-9535 123 | year: '2022' 124 | url: https://CRAN.R-project.org/package=rgee 125 | - type: software 126 | title: rjson 127 | abstract: 'rjson: JSON for R' 128 | notes: Imports 129 | authors: 130 | - family-names: Couture-Beil 131 | given-names: Alex 132 | email: rjson_pkg@mofo.ca 133 | year: '2022' 134 | url: https://CRAN.R-project.org/package=rjson 135 | - type: software 136 | title: sf 137 | abstract: 'sf: Simple Features for R' 138 | notes: Imports 139 | authors: 140 | - family-names: Pebesma 141 | given-names: Edzer 142 | email: edzer.pebesma@uni-muenster.de 143 | orcid: https://orcid.org/0000-0001-8049-7069 144 | year: '2022' 145 | url: https://CRAN.R-project.org/package=sf 146 | - type: software 147 | title: 'R: A Language and Environment for Statistical Computing' 148 | notes: Depends 149 | authors: 150 | - name: R Core Team 151 | location: 152 | name: Vienna, Austria 153 | year: '2022' 154 | url: https://www.R-project.org/ 155 | institution: 156 | name: R Foundation for Statistical Computing 157 | version: '>= 2.10' 158 | -------------------------------------------------------------------------------- /man/addEEtoSpOcc_single.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addEEtoSpOcc_single.R 3 | \name{addEEtoSpOcc_single} 4 | \alias{addEEtoSpOcc_single} 5 | \title{Add Google Earth Engine covariate data to a list for use in spOccupancy} 6 | \usage{ 7 | addEEtoSpOcc_single(spOcc, ee_data) 8 | } 9 | \arguments{ 10 | \item{spOcc}{a list containing ABAP detection/non-detection data returned by 11 | \code{\link{abapToSpOcc_single}}.} 12 | 13 | \item{ee_data}{a data frame with GEE data extracted using \code{\link{addVarEEcollection}} 14 | or \code{\link{addVarEEimage}}. The data frame needs to contain a column called 15 | \code{pentad} with the pentad ID from data extracted using the GEE functions. 16 | The remaining columns should only contain the GEE covariate values that are 17 | intended to be added to the \code{spOccupancy} list. For ease of use in occupancy 18 | model formula notation it's recommended that the variable names in the data 19 | frame are concise and informative, and don't contain spaces. See the example 20 | below for how to create this data frame after extracting GEE data.} 21 | } 22 | \description{ 23 | Google Earth Engine (GEE) data for each pentad can be extracted 24 | to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} 25 | functions. \code{addEEtoSpOcc_single} can then be used to add these types of data 26 | to a list in order to fit single-species occupancy models using \code{\link[spOccupancy]{spPGOcc}} 27 | (spatial) or \code{\link[spOccupancy]{PGOcc}} (non-spatial) from the \code{spOccupancy} 28 | package. 29 | } 30 | \note{ 31 | The numeric ranges of various GEE data can be vastly different so it 32 | is advised that you scale your covariate data before running an occupancy 33 | model. See the example below for how to do this. 34 | } 35 | \examples{ 36 | \dontrun{ 37 | library(rgee) 38 | library(ABDtools) 39 | library(dplyr) 40 | 41 | ## Extract ABAP pentad data 42 | abap_pentads <- getRegionPentads(.region_type = "province", 43 | .region = "Eastern Cape") 44 | 45 | ## Extract single season ABAP bird data 46 | abap_single <- getAbapData(.spp_code = 212, 47 | .region_type = "province", 48 | .region = "Eastern Cape", 49 | .years = 2012) 50 | 51 | ## Create spOcc list (with XY coordinates as site covariates) 52 | spOcc_single <- abapToSpOcc_single(abap_single, abap_pentads) 53 | str(spOcc_single) 54 | 55 | ## Start up GEE 56 | ee_check() 57 | ee_Initialize(drive = TRUE) 58 | 59 | ## Create assetId for pentads of interest 60 | assetId <- file.path(ee_get_assethome(), 'EC_pentads') 61 | 62 | ## Upload to pentads to GEE (only run this once per asset) 63 | uploadFeaturesToEE(pentads = abap_pentads, 64 | asset_id = assetId, 65 | load = FALSE) 66 | 67 | ## Load the remote asset into R session 68 | pentads <- ee$FeatureCollection(assetId) 69 | 70 | ## Extract spatial mean NDVI for each pentad 71 | ndvi_mean <- addVarEEcollection(ee_pentads = pentads, 72 | collection = "MODIS/006/MOD13A2", 73 | dates = c("2010-01-01", "2013-01-01"), 74 | temp_reducer = "mean", 75 | spt_reducer = "mean", 76 | bands = "NDVI") 77 | 78 | ## Extract spatial standard deviation of NDVI for each pentad 79 | ndvi_sd <- addVarEEcollection(ee_pentads = pentads, 80 | collection = "MODIS/006/MOD13A2", 81 | dates = c("2010-01-01", "2013-01-01"), 82 | temp_reducer = "mean", 83 | spt_reducer = "stdDev", 84 | bands = "NDVI") 85 | 86 | ## Create a site covariate data frame for input into addEEtoSpOcc_single(). 87 | ## Note the first column is called "pentad" which is a requirement for the 88 | ## function to work properly. 89 | my_ee_data <- bind_cols(pentad = ndvi_mean$pentad, 90 | ndvi_SD = ndvi_sd$NDVI_stdDev, 91 | ndvi_MEAN = ndvi_mean$NDVI_mean) 92 | 93 | ## Add GEE covariates to spOcc list 94 | spOcc_single_ee <- addEEtoSpOcc_single(spOcc = spOcc_single, 95 | ee_data = my_ee_data) 96 | str(spOcc_single_ee) 97 | 98 | 99 | ## Scale site covariates if necessary 100 | spOcc_single_ee$occ.covs <- scale(spOcc_single_ee$occ.covs) 101 | head(spOcc_single_ee$occ.covs) 102 | summary(spOcc_single_ee$occ.covs) 103 | 104 | 105 | ## A slightly different example: 106 | ## Annotate ABAP data with multiple bands from a GEE collection 107 | pentads_tc <- addVarEEcollection(ee_pentads = pentads, 108 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 109 | dates = c("2010-01-01", "2011-01-01"), 110 | temp_reducer = "mean", 111 | spt_reducer = "mean", 112 | bands = c("tmmx", "tmmn")) 113 | 114 | ## Select the variables to transfer to the spOcc list, making sure 115 | ## 'pentad' is amongst them 116 | my_ee_data <- pentads_tc \%>\% 117 | select(pentad, tmmx_mean, tmmn_mean) 118 | 119 | ## Add GEE covariates to spOcc list 120 | spOcc_single_ee <- addEEtoSpOcc_single(spOcc = spOcc_single, 121 | ee_data = my_ee_data) 122 | 123 | str(spOcc_single_ee) 124 | 125 | } 126 | } 127 | \seealso{ 128 | \code{\link{abapToSpOcc_single}}, \code{\link[spOccupancy]{spPGOcc}}, 129 | \code{\link[spOccupancy]{PGOcc}}, \code{\link{addVarEEimage}}, 130 | \code{\link{addVarEEcollection}} 131 | } 132 | \author{ 133 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 134 | Pachi Cervantes 135 | } 136 | -------------------------------------------------------------------------------- /R/abapToUnmarked_single.R: -------------------------------------------------------------------------------- 1 | #' ABAP to unmarked (single-season) 2 | #' 3 | #' @description This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 4 | #' into an \code{\link[unmarked]{unmarkedFrameOccu}} object which can be used to 5 | #' fit single-season occupancy models using \code{\link[unmarked]{occu}} (MacKenzie et. al 2002) 6 | #' or \code{\link[unmarked]{occuRN}} (Royle and Nichols, 2003) in `unmarked`. 7 | #' 8 | #' \code{\link[unmarked]{unmarkedFrameOccu}} objects can also be used to fit \code{\link[ubms]{stan_occu}} 9 | #' or \code{\link[ubms]{stan_occuRN}} models from the `ubms` package (which fits 10 | #' Unmarked Bayesian Models with Stan). 11 | #' 12 | #' 13 | #' @param abap_data single-season ABAP data downloaded using \code{\link{getAbapData}} 14 | #' @param pentads an `sf` object returned by \code{\link{getRegionPentads}}. 15 | #' Defaults to `NULL`. 16 | #' 17 | #' @details In addition to reformatting the detection/non-detection ABAP data 18 | #' for use in `unmarked` and `ubms` occupancy models, this function also extracts 19 | #' two survey-level covariates: ` hours` and `jday`. The `hours` variable is the 20 | #' total number of hours spent atlassing which is recorded on the pentad card and 21 | #' `jday` is the Julian day corresponding to the first day of atlassing for that 22 | #' card. If `pentads` are provided the `unmarked` frame will add the x and y 23 | #' coordinates as site covariates (`siteCovs`). The spatial data can be used as 24 | #' random effects to run a restricted spatial regression (RSR) occupancy model 25 | #' in `ubms`. See \code{\link[ubms]{RSR}} for more details. 26 | #' 27 | #' @return an object of class \code{\link[unmarked]{unmarkedFrameOccu}} 28 | #' 29 | #' @note It's important to make sure that the `.region_type` and `.region` are 30 | #' the same when extracting `abap_data` and `pentads` (see example below). The 31 | #' processing time of `abapToUnmarked_single` can be considerably long if the 32 | #' number of cards and pentads of the focal species is high, so patience may be 33 | #' required. 34 | 35 | #' 36 | #' @seealso \code{\link[unmarked]{occu}}, \code{\link[unmarked]{occuRN}}, 37 | #' \code{\link[ubms]{stan_occu}}, \code{\link[ubms]{stan_occuRN}} 38 | #' 39 | #' @author Dominic Henry \cr 40 | #' Pachi Cervantes 41 | #' 42 | #' @references 43 | #' MacKenzie, D. I., J. D. Nichols, G. B. Lachman, S. Droege, J. Andrew Royle, 44 | #' and C. A. Langtimm. 2002. Estimating Site Occupancy Rates When Detection 45 | #' Probabilities Are Less Than One. Ecology 83: 2248-2255. 46 | #' 47 | #' Royle, J. A. and Nichols, J. D. (2003) Estimating Abundance from Repeated 48 | #' Presence-Absence 49 | #' Data or Point Counts. Ecology, 84(3) pp. 777-790. 50 | #' @export 51 | #' 52 | #' @examples 53 | #' \dontrun{ 54 | #' abap_single <- getAbapData(.spp_code = 212, 55 | #' .region_type = "province", 56 | #' .region = "Eastern Cape", 57 | #' .years = 2012) 58 | #' 59 | #' abap_pentads <- getRegionPentads(.region_type = "province", 60 | #' .region = "Eastern Cape") 61 | #' 62 | #' ## Return unmarked frame no site covariates 63 | #' um_df <- abapToUnmarked_single(abap_single) 64 | #' 65 | #' ## Return unmarked frame with Pentad coordinates as site covariates 66 | #' um_df <- abapToUnmarked_single(abap_single, abap_pentads) 67 | #'} 68 | abapToUnmarked_single <- function(abap_data, pentads = NULL){ 69 | 70 | if(!requireNamespace("unmarked", quietly = TRUE)) { 71 | stop("Package unmarked doesn't seem to be installed. Please install before using this function.", 72 | call. = FALSE) 73 | } 74 | 75 | pentad_id <- unique(abap_data$Pentad) 76 | 77 | max_visits <- abap_data %>% 78 | dplyr::count(Pentad) %>% 79 | dplyr::pull(n) %>% 80 | max() 81 | 82 | ## Extract spatial data 83 | if(!is.null(pentads)){ 84 | 85 | sf::st_agr(pentads) = "constant" 86 | 87 | pentad_xy <- pentads %>% 88 | dplyr::filter(pentad %in% pentad_id) %>% 89 | dplyr::arrange(pentad) %>% 90 | sf::st_centroid() %>% 91 | sf::st_coordinates() %>% 92 | as.data.frame() %>% 93 | dplyr::rename_all(tolower) 94 | 95 | } 96 | 97 | # Aux padding vector 98 | vpad <- rep(NA, max_visits) 99 | 100 | ## Create dataframe to format 101 | format_df <- abap_data %>% 102 | dplyr::select(Pentad, Spp, TotalHours, StartDate) %>% 103 | dplyr::mutate(Spp = ifelse(Spp == "-", 0L, 1L), 104 | julian_day = lubridate::yday(StartDate)) %>% 105 | dplyr::nest_by(Pentad) %>% 106 | dplyr::arrange(Pentad) %>% 107 | dplyr::mutate(hourpad = list(head(c(data$TotalHours, vpad), max_visits)), 108 | jdaypad = list(head(c(data$julian_day, vpad), max_visits))) 109 | 110 | ## Extract detection histories 111 | det_hist <- format_df %>% 112 | dplyr::mutate(dets = list(head(c(data$Spp, vpad), max_visits))) 113 | 114 | Y <- do.call("rbind", det_hist$dets) 115 | rownames(Y) <- format_df$Pentad 116 | 117 | ## Extract total hours 118 | obs_hours <- do.call("rbind", format_df$hourpad) 119 | rownames(obs_hours) <- format_df$Pentad 120 | 121 | ## Extract Julian day 122 | obs_jday <- do.call("rbind", format_df$jdaypad) 123 | rownames(obs_jday) <- format_df$Pentad 124 | 125 | obs_covs <- list(hours = as.data.frame(obs_hours), 126 | jday = as.data.frame(obs_jday)) 127 | 128 | ## Create unmarked data frame 129 | if(!is.null(pentads)){ 130 | 131 | umf_abap <- unmarked::unmarkedFrameOccu(y = Y, 132 | siteCovs = pentad_xy, 133 | obsCovs = obs_covs, 134 | mapInfo = NULL) 135 | 136 | } else if (is.null(pentads)){ 137 | 138 | umf_abap <- unmarked::unmarkedFrameOccu(y = Y, 139 | obsCovs = obs_covs, 140 | mapInfo = NULL) 141 | } 142 | 143 | return(umf_abap) 144 | } 145 | -------------------------------------------------------------------------------- /man/addEEtoUnmarked_single.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addEEtoUnmarked_single.R 3 | \name{addEEtoUnmarked_single} 4 | \alias{addEEtoUnmarked_single} 5 | \title{Add Google Earth Engine covariate data to a single-season Unmarked frame} 6 | \usage{ 7 | addEEtoUnmarked_single(umf, ee_data) 8 | } 9 | \arguments{ 10 | \item{umf}{a single-season Unmarked frame containing ABAP detection/non-detection data returned by \code{\link{abapToUnmarked_single}}.} 11 | 12 | \item{ee_data}{a data frame with GEE data extracted using \code{\link{addVarEEcollection}} or \code{\link{addVarEEimage}}. The data frame needs to contain a column called \code{pentads} with the pentad ID from data extracted using the GEE functions. The remaining columns should only contain the GEE covariate values that are intended to be added to the \code{unmarked} frame. For ease of use in occupancy model formula notation it's recommended that the variable names in the data frame are concise and informative, and don't contain spaces. See the example below for how to create this data frame after extracting GEE data.} 13 | } 14 | \value{ 15 | an object of class \code{\link[unmarked]{unmarkedFrameOccu}} with survey and site covariates. 16 | } 17 | \description{ 18 | Google Earth Engine (GEE) data for each pentad can be extracted to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} functions. \code{addEEtoUnmarked_single} can then be used to add these types of data to a single-season Unmarked frame. GEE data can subsquently be used as covariates in single-season occupancy models such as \code{\link[unmarked]{occu}}, \code{\link[unmarked]{occuRN}}, \code{\link[ubms]{stan_occu}} or \code{\link[ubms]{stan_occuRN}}. 19 | } 20 | \note{ 21 | The numeric ranges of various GEE data can be vastly different so it is advised that you scale your covariate data before running an occupancy model. This can be done within the formula notation of the various \code{\link[unmarked]{occu}} functions. 22 | } 23 | \examples{ 24 | \dontrun{ 25 | library(rgee) 26 | library(ABDtools) 27 | library(unmarked) 28 | library(dplyr) 29 | 30 | ## Extract ABAP pentad data 31 | abap_pentads <- getRegionPentads(.region_type = "province", 32 | .region = "Eastern Cape") 33 | 34 | ## Extract single season ABAP bird data 35 | abap_single <- getAbapData(.spp_code = 212, 36 | .region_type = "province", 37 | .region = "Eastern Cape", 38 | .years = 2012) 39 | 40 | ## Create unmarked frame (with X & Y coords as site covariates) 41 | umf_single <- abapToUnmarked_single(abap_single, abap_pentads) 42 | summary(umf_single) 43 | 44 | ## Start up GEE 45 | ee_check() 46 | ee_Initialize(drive = TRUE) 47 | 48 | ## Create assetId for pentads of interest 49 | assetId <- sprintf("\%s/\%s", ee_get_assethome(), 'EC_pentads') 50 | 51 | ## Upload to pentads to GEE (only run this once per asset) 52 | uploadFeaturesToEE(pentads = abap_pentads, 53 | asset_id = assetId, 54 | load = FALSE) 55 | 56 | ## Load the remote asset into R session 57 | pentads <- ee$FeatureCollection(assetId) 58 | 59 | ## Extract spatial mean NDVI for each pentad 60 | ndvi_mean <- addVarEEcollection(ee_pentads = pentads, 61 | collection = "MODIS/006/MOD13A2", 62 | dates = c("2010-01-01", "2013-01-01"), 63 | temp_reducer = "mean", 64 | spt_reducer = "mean", 65 | bands = "NDVI") 66 | 67 | ## Extract spatial standard deviation of NDVI for each pentad 68 | ndvi_sd <- addVarEEcollection(ee_pentads = pentads, 69 | collection = "MODIS/006/MOD13A2", 70 | dates = c("2010-01-01", "2013-01-01"), 71 | temp_reducer = "mean", 72 | spt_reducer = "stdDev", 73 | bands = "NDVI") 74 | 75 | ## Extract spatial minimum land surface temperature for each pentad 76 | lst_min <- addVarEEcollection(ee_pentads = pentads, 77 | collection = "MODIS/061/MOD11A1", 78 | dates = c("2010-01-01", "2011-01-01"), 79 | temp_reducer = "mean", 80 | spt_reducer = "min", 81 | bands = "LST_Day_1km") 82 | 83 | ## Extract spatial maximum land surface temperature for each pentad 84 | lst_max <- addVarEEcollection(ee_pentads = pentads, 85 | collection = "MODIS/061/MOD11A1", 86 | dates = c("2010-01-01", "2011-01-01"), 87 | temp_reducer = "mean", 88 | spt_reducer = "max", 89 | bands = "LST_Day_1km") 90 | 91 | ## Create a site covariate data frame for input into addEEtoUnmarked_single(). 92 | ## Note the first column is called "pentad" which is a requirement for the function to work properly. 93 | my_ee_data <- bind_cols(pentad = ndvi_mean$pentad, 94 | ndvi_SD = ndvi_sd$NDVI_stdDev, 95 | ndvi_MEAN = ndvi_mean$NDVI_mean, 96 | temp_MIN = lst_min$LST_Day_1km_min, 97 | temp_MAX = lst_max$LST_Day_1km_max) 98 | 99 | ## Add GEE covariates to unmarked frame 100 | umf_single_ee <- addEEtoUnmarked_single(umf = umf_single, 101 | ee_data = my_ee_data) 102 | summary(umf_single_ee) 103 | 104 | ## A slightly different example: 105 | ## Annotate ABAP data with multiple bands from a GEE collection 106 | pentads_tc <- addVarEEcollection(ee_pentads = pentads, 107 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 108 | dates = c("2010-01-01", "2011-01-01"), 109 | temp_reducer = "mean", 110 | spt_reducer = "mean", 111 | bands = c("tmmx", "tmmn")) 112 | 113 | ## Select the variables to transfer to the unmarked frame, making sure 114 | ## 'pentad' is amongst them 115 | my_ee_data <- pentads_tc \%>\% 116 | select(pentad, tmmx_mean, tmmn_mean) 117 | 118 | ## Add GEE covariates to unmarked frame 119 | umf_single_ee <- addEEtoUnmarked_single(umf = umf_single, 120 | ee_data = my_ee_data) 121 | 122 | summary(umf_single_ee) 123 | 124 | } 125 | } 126 | \seealso{ 127 | \code{\link{abapToUnmarked_single}}, \code{\link{addVarEEimage}}, \code{\link{addVarEEcollection}} 128 | } 129 | \author{ 130 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 131 | Pachi Cervantes 132 | } 133 | -------------------------------------------------------------------------------- /R/abapToSpOcc_single.R: -------------------------------------------------------------------------------- 1 | #' ABAP to spOccupancy (single-species) 2 | #' 3 | #' @description This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 4 | #' into an list which can be used to fit single-species occupancy models using 5 | #' \code{\link[spOccupancy]{spPGOcc}} (spatial) or \code{\link[spOccupancy]{PGOcc}} 6 | #' (non-spatial). The `spOccupancy` package fits single-species, multi-species, 7 | #' and integrated non-spatial and spatial occupancy models using Markov Chain Monte Carlo (MCMC). 8 | #' 9 | #' @param abap_data single-season ABAP data downloaded using \code{\link{getAbapData}}. 10 | #' @param pentads an `sf` object returned by \code{\link{getRegionPentads}}. Defaults to `NULL`. 11 | #' @param proj_coords logical value indicating whether pentad coordinates are 12 | #' projected (`TRUE`) or kept in decimal degree format (`FALSE`). Defaults to `TRUE`. 13 | #' See details below for coordinate reference system used during transformation. 14 | #' 15 | #' @return A list containing data necessary for model fitting in `spOccupancy`. 16 | #' List elements are `y` (detection/non-detection data), `det.covs` (survey-level covariates), 17 | #' and `coords` (x and y centroids of pentads if spatial data are supplied). 18 | #' 19 | #' @details The \code{\link[spOccupancy]{spPGOcc}} function takes `coords` as an 20 | #' argument with X and Y coordinates included for each site. Within the context 21 | #' of ABAP, these `coords` are the centroid of each sampling pentad. In order to 22 | #' provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 23 | #' and provide the same inputs for `.region_type` and `.region` that are specified 24 | #' in corresponding \code{\link{getAbapData}} call. If proj_coords is set to `TRUE` 25 | #' then the coordinates will be transformed using the African Albers Equal Area 26 | #' coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 27 | #' for details). This projection is best suited for land masses extending in an 28 | #' east-to-west orientation at mid-latitudes making it suitable for projecting 29 | #' pentads in Southern Africa. The functions in the `spOccupancy` package assume 30 | #' that coordinates are projected so for best results it is recommended to always 31 | #' project the data. \cr 32 | #' 33 | #' If `pentads` are specified then the output can be automatically used in 34 | #' \code{\link[spOccupancy]{spPGOcc}}. If no spatial data are provided the output 35 | #' can be used in \code{\link[spOccupancy]{PGOcc}}.\cr 36 | #' 37 | #' In addition to reformatting the detection/non-detection ABAP data for use in 38 | #' `spOccupancy` occupancy models, this function also extracts two survey-level 39 | #' covariates and adds them to the output list: ` hours` and `jday`. The `hours` 40 | #' variable is the total number of hours spent atlassing which is recorded on the 41 | #' pentad card and `jday` is the Julian day corresponding to the first day of 42 | #' atlassing for that card. 43 | #' 44 | #' @note The processing time of `abapToSpOcc_single` can be considerably long if 45 | #' the number of cards and pentads of the focal species is high, so patience may 46 | #' be required. 47 | #' 48 | #' @author Dominic Henry \cr 49 | #' Pachi Cervantes 50 | #' @seealso \code{\link[spOccupancy]{spPGOcc}}, \code{\link[spOccupancy]{PGOcc}} 51 | #' @export 52 | #' 53 | #' @examples 54 | #' abap_data <- getAbapData(.spp_code = 212, 55 | #' .region_type = "province", 56 | #' .region = "Eastern Cape", 57 | #' .years = 2012) 58 | #' 59 | #' abap_pentads <- getRegionPentads(.region_type = "province", 60 | #' .region = "Eastern Cape") 61 | #' 62 | #' 63 | #' ## Return list for spatial occupancy model 64 | #' spOcc <- abapToSpOcc_single(abap_data, abap_pentads) 65 | #' str(spOcc) 66 | #' 67 | #' ## Return list for spatial occupancy model (without coordinate projection) 68 | #' spOcc <- abapToSpOcc_single(abap_data, abap_pentads, proj_coords = FALSE) 69 | #' str(spOcc) 70 | #' 71 | #' ## List for non-spatial occupancy model 72 | #' spOcc <- abapToSpOcc_single(abap_data) 73 | #' str(spOcc) 74 | #' 75 | abapToSpOcc_single <- function(abap_data, pentads = NULL, proj_coords = TRUE){ 76 | 77 | if(!requireNamespace("spOccupancy", quietly = TRUE)) { 78 | warning("Package spOccupancy doesn't seem to be installed. We recommend installing it if you are using this function.") 79 | } 80 | 81 | pentad_id <- unique(abap_data$Pentad) 82 | 83 | max_visits <- abap_data %>% 84 | dplyr::count(Pentad) %>% 85 | dplyr::pull(n) %>% 86 | max() 87 | 88 | ## Extract spatial data 89 | if(!is.null(pentads)){ 90 | 91 | sf::st_agr(pentads) = "constant" 92 | aeaproj <- "+proj=aea +lat_1=20 +lat_2=-23 +lat_0=0 +lon_0=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs" 93 | 94 | if(isTRUE(proj_coords)){ 95 | pentads <- sf::st_transform(pentads, aeaproj) 96 | } 97 | 98 | pentad_xy <- pentads %>% 99 | dplyr::filter(pentad %in% pentad_id) %>% 100 | dplyr::arrange(pentad) %>% 101 | sf::st_centroid() %>% 102 | sf::st_coordinates() 103 | } 104 | 105 | # Aux padding vector 106 | vpad <- rep(NA, max_visits) 107 | 108 | ## Create dataframe to format 109 | format_df <- abap_data %>% 110 | dplyr::select(Pentad, Spp, TotalHours, StartDate) %>% 111 | dplyr::mutate(Spp = ifelse(Spp == "-", 0L, 1L), 112 | julian_day = lubridate::yday(StartDate)) %>% 113 | dplyr::nest_by(Pentad) %>% 114 | dplyr::arrange(Pentad) %>% 115 | dplyr::mutate(hourpad = list(head(c(data$TotalHours, vpad), max_visits)), 116 | jdaypad = list(head(c(data$julian_day, vpad), max_visits))) 117 | 118 | ## Extract detection histories 119 | det_hist <- format_df %>% 120 | dplyr::mutate(dets = list(head(c(data$Spp, vpad), max_visits))) 121 | 122 | Y <- do.call("rbind", det_hist$dets) 123 | rownames(Y) <- format_df$Pentad 124 | 125 | ## Extract total hours 126 | obs_hours <- do.call("rbind", format_df$hourpad) 127 | rownames(obs_hours) <- format_df$Pentad 128 | 129 | ## Extract Julian day 130 | obs_jday <- do.call("rbind", format_df$jdaypad) 131 | rownames(obs_jday) <- format_df$Pentad 132 | 133 | if(!is.null(pentads)){ 134 | 135 | spocc_data <- list(y = Y, 136 | coords = pentad_xy, 137 | det.covs = list(hours = obs_hours, jday = obs_jday)) 138 | 139 | } else if (is.null(pentads)){ 140 | 141 | spocc_data <- list(y = Y, 142 | det.covs = list(hours = obs_hours, jday = obs_jday)) 143 | } 144 | 145 | return(spocc_data) 146 | 147 | } 148 | -------------------------------------------------------------------------------- /R/addEEtoSpOcc_single.R: -------------------------------------------------------------------------------- 1 | #' Add Google Earth Engine covariate data to a list for use in spOccupancy 2 | #' 3 | #' @description Google Earth Engine (GEE) data for each pentad can be extracted 4 | #' to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} 5 | #' functions. `addEEtoSpOcc_single` can then be used to add these types of data 6 | #' to a list in order to fit single-species occupancy models using \code{\link[spOccupancy]{spPGOcc}} 7 | #' (spatial) or \code{\link[spOccupancy]{PGOcc}} (non-spatial) from the `spOccupancy` 8 | #' package. 9 | #' 10 | #' @param spOcc a list containing ABAP detection/non-detection data returned by 11 | #' \code{\link{abapToSpOcc_single}}. 12 | #' @param ee_data a data frame with GEE data extracted using \code{\link{addVarEEcollection}} 13 | #' or \code{\link{addVarEEimage}}. The data frame needs to contain a column called 14 | #' `pentad` with the pentad ID from data extracted using the GEE functions. 15 | #' The remaining columns should only contain the GEE covariate values that are 16 | #' intended to be added to the `spOccupancy` list. For ease of use in occupancy 17 | #' model formula notation it's recommended that the variable names in the data 18 | #' frame are concise and informative, and don't contain spaces. See the example 19 | #' below for how to create this data frame after extracting GEE data. 20 | #' 21 | #' @note The numeric ranges of various GEE data can be vastly different so it 22 | #' is advised that you scale your covariate data before running an occupancy 23 | #' model. See the example below for how to do this. 24 | #' 25 | #' @author Dominic Henry \cr 26 | #' Pachi Cervantes 27 | #' 28 | #' @seealso \code{\link{abapToSpOcc_single}}, \code{\link[spOccupancy]{spPGOcc}}, 29 | #' \code{\link[spOccupancy]{PGOcc}}, \code{\link{addVarEEimage}}, 30 | #' \code{\link{addVarEEcollection}} 31 | #' 32 | #' @export 33 | #' 34 | #' @examples 35 | #' \dontrun{ 36 | #' library(rgee) 37 | #' library(ABDtools) 38 | #' library(dplyr) 39 | #' 40 | #' ## Extract ABAP pentad data 41 | #' abap_pentads <- getRegionPentads(.region_type = "province", 42 | #' .region = "Eastern Cape") 43 | #' 44 | #' ## Extract single season ABAP bird data 45 | #' abap_single <- getAbapData(.spp_code = 212, 46 | #' .region_type = "province", 47 | #' .region = "Eastern Cape", 48 | #' .years = 2012) 49 | #' 50 | #' ## Create spOcc list (with XY coordinates as site covariates) 51 | #' spOcc_single <- abapToSpOcc_single(abap_single, abap_pentads) 52 | #' str(spOcc_single) 53 | #' 54 | #' ## Start up GEE 55 | #' ee_check() 56 | #' ee_Initialize(drive = TRUE) 57 | #' 58 | #' ## Create assetId for pentads of interest 59 | #' assetId <- file.path(ee_get_assethome(), 'EC_pentads') 60 | #' 61 | #' ## Upload to pentads to GEE (only run this once per asset) 62 | #' uploadFeaturesToEE(pentads = abap_pentads, 63 | #' asset_id = assetId, 64 | #' load = FALSE) 65 | #' 66 | #' ## Load the remote asset into R session 67 | #' pentads <- ee$FeatureCollection(assetId) 68 | #' 69 | #' ## Extract spatial mean NDVI for each pentad 70 | #' ndvi_mean <- addVarEEcollection(ee_pentads = pentads, 71 | #' collection = "MODIS/006/MOD13A2", 72 | #' dates = c("2010-01-01", "2013-01-01"), 73 | #' temp_reducer = "mean", 74 | #' spt_reducer = "mean", 75 | #' bands = "NDVI") 76 | #' 77 | #' ## Extract spatial standard deviation of NDVI for each pentad 78 | #' ndvi_sd <- addVarEEcollection(ee_pentads = pentads, 79 | #' collection = "MODIS/006/MOD13A2", 80 | #' dates = c("2010-01-01", "2013-01-01"), 81 | #' temp_reducer = "mean", 82 | #' spt_reducer = "stdDev", 83 | #' bands = "NDVI") 84 | #' 85 | #' ## Create a site covariate data frame for input into addEEtoSpOcc_single(). 86 | #' ## Note the first column is called "pentad" which is a requirement for the 87 | #' ## function to work properly. 88 | #' my_ee_data <- bind_cols(pentad = ndvi_mean$pentad, 89 | #' ndvi_SD = ndvi_sd$NDVI_stdDev, 90 | #' ndvi_MEAN = ndvi_mean$NDVI_mean) 91 | #' 92 | #' ## Add GEE covariates to spOcc list 93 | #' spOcc_single_ee <- addEEtoSpOcc_single(spOcc = spOcc_single, 94 | #' ee_data = my_ee_data) 95 | #' str(spOcc_single_ee) 96 | #' 97 | #' 98 | #' ## Scale site covariates if necessary 99 | #' spOcc_single_ee$occ.covs <- scale(spOcc_single_ee$occ.covs) 100 | #' head(spOcc_single_ee$occ.covs) 101 | #' summary(spOcc_single_ee$occ.covs) 102 | #' 103 | #' 104 | #' ## A slightly different example: 105 | #' ## Annotate ABAP data with multiple bands from a GEE collection 106 | #' pentads_tc <- addVarEEcollection(ee_pentads = pentads, 107 | #' collection = "IDAHO_EPSCOR/TERRACLIMATE", 108 | #' dates = c("2010-01-01", "2011-01-01"), 109 | #' temp_reducer = "mean", 110 | #' spt_reducer = "mean", 111 | #' bands = c("tmmx", "tmmn")) 112 | #' 113 | #' ## Select the variables to transfer to the spOcc list, making sure 114 | #' ## 'pentad' is amongst them 115 | #' my_ee_data <- pentads_tc %>% 116 | #' select(pentad, tmmx_mean, tmmn_mean) 117 | #' 118 | #' ## Add GEE covariates to spOcc list 119 | #' spOcc_single_ee <- addEEtoSpOcc_single(spOcc = spOcc_single, 120 | #' ee_data = my_ee_data) 121 | #' 122 | #' str(spOcc_single_ee) 123 | #' 124 | #' } 125 | 126 | addEEtoSpOcc_single <- function(spOcc, ee_data) { 127 | 128 | if(!requireNamespace("spOccupancy", quietly = TRUE)) { 129 | warning("Package spOccupancy doesn't seem to be installed. We recommend installing it if you are using this function.") 130 | } 131 | 132 | if(isFALSE("pentad" %in% names(ee_data))){ 133 | stop("ee_data does not contain the required 'pentad' variable. See function documentation.") 134 | } 135 | 136 | spOcc_pentads <- dimnames(spOcc$y)[[1]] 137 | 138 | site_cov <- ee_data %>% 139 | as.data.frame() %>% 140 | dplyr::select(-dplyr::any_of("geometry")) %>% 141 | dplyr::filter(pentad %in% spOcc_pentads) %>% 142 | dplyr::arrange(match(pentad, spOcc_pentads)) 143 | 144 | # check that pentads in spOccupancy data and covariate data are the same 145 | if(!identical(site_cov$pentad, spOcc_pentads)){ 146 | stop("Pentads in spOccupancy data and covariate data don't match") 147 | } 148 | 149 | site_cov <- site_cov %>% 150 | dplyr::select(-pentad) 151 | 152 | if(is.null(spOcc$occ.covs)) { 153 | spOcc$occ.covs <- as.matrix(site_cov) 154 | } else { 155 | spOcc$occ.covs <- as.matrix(cbind(spOcc$occ.covs, site_cov)) 156 | } 157 | 158 | 159 | return(spOcc) 160 | } 161 | -------------------------------------------------------------------------------- /man/addEEtoSpOcc_multi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addEEtoSpOcc_multi.R 3 | \name{addEEtoSpOcc_multi} 4 | \alias{addEEtoSpOcc_multi} 5 | \title{Add Google Earth Engine covariate data to a multi-season spOccupancy data list} 6 | \usage{ 7 | addEEtoSpOcc_multi( 8 | spOcc, 9 | ee_data, 10 | ee_assign, 11 | process = c("occ", "det"), 12 | seasons = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{spOcc}{a list containing ABAP detection/non-detection data returned by 17 | \code{\link{abapToSpOcc_multi}}.} 18 | 19 | \item{ee_data}{a data frame with GEE data extracted using \code{\link{addVarEEcollection}} 20 | or \code{\link{addVarEEimage}}. The data frame needs to contain a column called 21 | \code{pentads} with the pentad ID from data extracted using the GEE functions. 22 | The remaining columns should only contain the GEE covariate values that are 23 | intended to be added to the \code{spOccupancy} list. For ease of use in occupancy 24 | model formula notation it's recommended that the variable names in the data 25 | frame are concise and informative, and don't contain spaces. See the example 26 | below for how to create this data frame after extracting GEE data.} 27 | 28 | \item{ee_assign}{"site" if the covariate only varies between sites or "site-season" 29 | if the covariate varies across sites and between seasons.} 30 | 31 | \item{process}{either 'occ' or 'det' specifying whether the covariate 32 | is affecting occupancy or detection processes, respectively.} 33 | 34 | \item{seasons}{string indicating the name of the variable in \code{ee_data} that should 35 | be used to define seasons in multi-season models.} 36 | } 37 | \value{ 38 | The data list \code{spOcc} with the additional covariates. 39 | } 40 | \description{ 41 | Google Earth Engine (GEE) data for each pentad can be extracted 42 | to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} 43 | functions. \code{addEEtoSpOcc_multi} can then be used to add these types of data 44 | to a list in order to fit single-species multi-season occupancy models using 45 | \code{\link[spOccupancy]{stPGOcc}} (spatial) or \code{\link[spOccupancy]{tPGOcc}} 46 | (non-spatial) from the \code{spOccupancy} package. 47 | } 48 | \details{ 49 | If ee_assign = "site-year" ee_data must be a data frame-like object (sf could work) 50 | with each covariate in one column, the pentad identifier in another column named \code{pentad}, 51 | and the season identifier in another column (with the same name specified in \code{season}). 52 | if ee_assign = "site" ee_data must be a data frame-like object 53 | with each covariate in one column, and the pentad identifier in another column named 'pentad'. 54 | } 55 | \note{ 56 | The numeric ranges of various GEE data can be vastly different so it 57 | is advised that you scale your covariate data before running an occupancy 58 | model. 59 | } 60 | \examples{ 61 | \dontrun{ 62 | ## rgee and ABDtools are required to annotate data with Google Earth Engine 63 | library(rgee) 64 | library(ABDtools) 65 | library(dplyr) 66 | 67 | ## Extract ABAP pentad data 68 | abap_pentads <- getRegionPentads(.region_type = "province", 69 | .region = "Eastern Cape") 70 | 71 | ## Extract multi-season ABAP bird data 72 | abap_multi <- getAbapData(.spp = 212, 73 | .region_type = "province", 74 | .region = "Eastern Cape", 75 | .years = c(2009,2010,2011,2012)) 76 | 77 | ## We will use years as occupancy reference seasons 78 | abap_multi$year <- format(abap_multi$StartDate, "\%Y") 79 | 80 | ## Create unmarked frame (with X & Y coords as site covariates) 81 | spOcc_multi <- abapToSpOcc_multi(abap_multi, abap_pentads, seasons = "year") 82 | str(spOcc_multi) 83 | 84 | ## Start up GEE 85 | ee_check() 86 | ee_Initialize(drive = TRUE) 87 | 88 | ## Create assetId for pentads of interest 89 | assetId <- file.path(ee_get_assethome(), 'EC_pentads') 90 | 91 | ## Upload to pentads to GEE (only run this once per asset) and 92 | ## load the remote asset into R session 93 | pentads <- uploadFeaturesToEE(feats = abap_pentads, 94 | asset_id = assetId, 95 | load = TRUE) 96 | 97 | ### ADD SITE-YEAR VARIABLES ### 98 | 99 | ## Create a multi-band image with mean NDVI for each year 100 | ndvi_multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 101 | dates = c("2009-01-01", "2012-12-31"), 102 | band = "NDVI", 103 | group_type = "year", 104 | groups = 2009:2012, 105 | reducer = "mean", 106 | unmask = FALSE) 107 | 108 | ## Find mean and sd NDVI value for each pentad and year from the multi-band image 109 | ndvi_mean <- addVarEEimage(pentads, ndvi_multiband, "mean") 110 | ndvi_sd <- addVarEEimage(pentads, ndvi_multiband, "stdDev") 111 | 112 | ## Format the data to include the pentad column and GEE values for each year 113 | ndvi_mean <- ndvi_mean \%>\% 114 | select(pentad, paste0("NDVI_", as.character(2009:2012))) 115 | 116 | ndvi_sd <- ndvi_sd \%>\% 117 | select(pentad, paste0("NDVI_", as.character(2009:2012))) 118 | 119 | ## Create a data frame with covariate columns, pentad and season. 120 | ee_siteyear <- ndvi_mean \%>\% 121 | as.data.frame() \%>\% 122 | dplyr::select(-geometry) \%>\% 123 | tidyr::pivot_longer(-pentad, names_to = "year", values_to = "ndvi_mean") 124 | 125 | ## Add GEE site-year data to spOccupancy data list. We will add these covariates 126 | ## to the detection process. 127 | spOcc_multi_ee1 <- addEEtoSpOcc_multi(spOcc_multi, 128 | ee_data = ee_siteyear, 129 | ee_assign = "site-season", 130 | process = "det", 131 | seasons = "year") 132 | 133 | str(spOcc_multi_ee1) 134 | 135 | ### ADD SITE VARIABLES ### 136 | 137 | ## Annotate data with mean elevation per pentad 138 | elev_mean <- addVarEEimage(ee_feats = pentads, 139 | image = "MERIT/DEM/v1_0_3", 140 | reducer = "mean", 141 | bands = "dem", 142 | unmask = FALSE) 143 | 144 | ## Keep only the columns that we need 145 | ee_site <- elev_mean \%>\% 146 | as.data.frame() \%>\% 147 | dplyr::select(pentad, dem_mean) 148 | 149 | ## Add GEE site data to spOccupancy data list. We will now add it to the 150 | ## occupancy process. 151 | spOcc_multi_ee2 <- addEEtoSpOcc_multi(spOcc_multi, 152 | ee_data = ee_site, 153 | ee_assign = "site", 154 | process = "occ") 155 | } 156 | } 157 | \seealso{ 158 | \code{\link{abapToSpOcc_multi}}, \code{\link[spOccupancy]{stPGOcc}}, 159 | \code{\link[spOccupancy]{tPGOcc}}, \code{\link[ABDtools]{addVarEEimage}}, 160 | \code{\link[ABDtools]{addVarEEcollection}} 161 | } 162 | \author{ 163 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 164 | Pachi Cervantes 165 | } 166 | -------------------------------------------------------------------------------- /man/abapToOccuR.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/abapToOccuR.R 3 | \name{abapToOccuR} 4 | \alias{abapToOccuR} 5 | \title{ABAP to occuR} 6 | \usage{ 7 | abapToOccuR(abap_data, occasion, pentads = NULL, proj_coords = TRUE) 8 | } 9 | \arguments{ 10 | \item{abap_data}{ABAP data downloaded using \code{\link{getAbapData}}.} 11 | 12 | \item{occasion}{A character string indicating the variable in \code{abap_data} 13 | that informs about the season (or occasion, as referred to in occuR). This must always 14 | be supplied, although it is really only important in the case of multi-season data. 15 | It is typically "year" but could be something else.} 16 | 17 | \item{pentads}{Optional, An \code{sf} object returned by \code{\link{getRegionPentads}}. Defaults to \code{NULL}.} 18 | 19 | \item{proj_coords}{logical value indicating whether pentad coordinates are 20 | projected (\code{TRUE}) or kept in decimal degree format (\code{FALSE}). Defaults to \code{TRUE}. 21 | See details below for coordinate reference system used during transformation.} 22 | } 23 | \value{ 24 | A list containing data necessary for model fitting in \code{occuR}. 25 | List elements are: visit_data, a data frame containing information about individual 26 | visits; site_data, a data frame containing information about sites and seasons. 27 | If \code{pentads} are given then the coordinates of the centroid of the pentads will be 28 | included in site_data. 29 | } 30 | \description{ 31 | This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 32 | into an list which can be used to fit single-species occupancy models using 33 | the package \href{https://github.com/r-glennie/occuR}{occuR}. This package 34 | can fit non-linear effects, including spatial, temporal and spatio-temporal effects 35 | using splines. 36 | } 37 | \details{ 38 | The \href{https://github.com/r-glennie/occuR}{occuR} package can 39 | fit spatial effects, for which we need the spatial location of our sites. Within the context 40 | of ABAP, these locations are the centroid of each sampling pentad. In order to 41 | provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 42 | and provide the same inputs for \code{.region_type} and \code{.region} that are specified 43 | in corresponding \code{\link{getAbapData}} call. If proj_coords is set to \code{TRUE} 44 | then the coordinates will be transformed using the African Albers Equal Area 45 | coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 46 | for details). This projection is best suited for land masses extending in an 47 | east-to-west orientation at mid-latitudes making it suitable for projecting 48 | pentads in Southern Africa. \cr 49 | 50 | In addition to reformatting the detection/non-detection ABAP data for use in 51 | \code{occuR} occupancy models, this function also extracts two survey-level 52 | covariates and adds them to the output list: \code{ hours} and \code{jday}. The \code{hours} 53 | variable is the total number of hours spent atlassing which is recorded on the 54 | pentad card and \code{jday} is the Julian day corresponding to the first day of 55 | atlassing for that card. 56 | } 57 | \examples{ 58 | \dontrun{ 59 | library(ABAP) 60 | library(rgee) 61 | library(ABDtools) 62 | library(dplyr) 63 | 64 | ## Download single-season ABAP data 65 | abap_data <- getAbapData(.spp_code = 212, 66 | .region_type = "province", 67 | .region = "Eastern Cape", 68 | .years = 2012) 69 | 70 | # Download ABAP site spatial data 71 | abap_pentads <- getRegionPentads(.region_type = "province", 72 | .region = "Eastern Cape") 73 | 74 | # We will use years as occupancy reference seasons 75 | abap_data$year <- format(abap_data$StartDate, "\%Y") 76 | 77 | ## Return list for spatial occupancy model 78 | occur_data <- abapToOccuR(abap_data, occasion = "year", abap_pentads) 79 | str(occur_data) 80 | 81 | ## Return list for spatial occupancy model (without coordinate projection) 82 | occur_data <- abapToOccuR(abap_data, "year", abap_pentads, proj_coords = FALSE) 83 | str(occur_data) 84 | 85 | ## List for non-spatial occupancy model 86 | occur_data <- abapToOccuR(abap_data, "year") 87 | str(occur_data) 88 | 89 | ## Transform multi-season ABAP data into occuR data is just as easy 90 | abap_data <- getAbapData(.spp_code = 212, 91 | .region_type = "province", 92 | .region = "Eastern Cape", 93 | .years = 2012:2015) 94 | 95 | # We will use years as occupancy reference seasons 96 | abap_data$year <- format(abap_data$StartDate, "\%Y") 97 | 98 | ## Return list for spatial occupancy model 99 | occur_data <- abapToOccuR(abap_data, occasion = "year", abap_pentads) 100 | str(occur_data) 101 | 102 | ### ADD SITE-YEAR VARIABLES ### 103 | 104 | ## Start up GEE 105 | ee_check() 106 | ee_Initialize(drive = TRUE) 107 | 108 | ## Create assetId for pentads of interest 109 | assetId <- file.path(ee_get_assethome(), 'EC_pentads') 110 | 111 | ## Upload to pentads to GEE (only run this once per asset) 112 | uploadFeaturesToEE(pentads = abap_pentads, 113 | asset_id = assetId, 114 | load = FALSE) 115 | 116 | ## Load the remote asset into R session 117 | pentads <- ee$FeatureCollection(assetId) 118 | 119 | ## Create a multi-band image with mean NDVI for each year 120 | ndvi_multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 121 | dates = c("2012-01-01", "2015-12-31"), 122 | band = "NDVI", 123 | group_type = "year", 124 | groups = 2012:2015, 125 | reducer = "mean", 126 | unmask = FALSE) 127 | 128 | ## Find mean and standard deviation of NDVI value for each pentad and year from the multi-band image 129 | ndvi_mean <- addVarEEimage(pentads, ndvi_multiband, "mean") 130 | ndvi_sd <- addVarEEimage(pentads, ndvi_multiband, "stdDev") 131 | 132 | ## Format the data to include the pentad column and GEE values for each year 133 | ndvi_mean <- ndvi_mean \%>\% 134 | select(pentad, paste0("NDVI_", as.character(2012:2015))) 135 | 136 | ndvi_sd <- ndvi_sd \%>\% 137 | select(pentad, paste0("NDVI_", as.character(2012:2015))) 138 | 139 | ## occuR data have the structure of regular data frames (they are data tables, but 140 | ## behave very similarly), so there are many ways we can transfer covariate values from 141 | ## other data frame-like objects. Here, we will transfer the value of these variables 142 | ## with dplyr::left_join(), but first we need to give covariates a long format with tidyr 143 | ndvi_mean_long <- ndvi_mean \%>\% 144 | sf::st_drop_geometry() \%>\% 145 | tidyr::pivot_longer(-pentad, names_to = "year", values_to = "NDVI_mean") \%>\% 146 | mutate(year = gsub("NDVI_", "", year)) 147 | 148 | ndvi_sd_long <- ndvi_sd \%>\% 149 | sf::st_drop_geometry() \%>\% 150 | tidyr::pivot_longer(-pentad, names_to = "year", values_to = "NDVI_sd") \%>\% 151 | mutate(year = gsub("NDVI_", "", year)) 152 | 153 | # Transfer variables via join 154 | occur_data_ee <- occur_data$site \%>\% 155 | dplyr::left_join(ndvi_mean_long, by = c("pentad", "year")) \%>\% 156 | dplyr::left_join(ndvi_sd_long, by = c("pentad", "year")) 157 | 158 | summary(occur_data_ee) 159 | 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /R/abapToUnmarked_multi.R: -------------------------------------------------------------------------------- 1 | #' ABAP to unmarked (multi-season) 2 | #' 3 | #' @description This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 4 | #' into an \code{\link[unmarked]{unmarkedMultFrame}} object which can be used to 5 | #' fit dynamic occupancy models using \code{\link[unmarked]{colext}} (MacKenzie et. al 2003) 6 | #' and \code{\link[ubms]{stan_colext}} from the `ubms` package (which fits 7 | #' Unmarked Bayesian Models with Stan). 8 | #' 9 | #' @param abap_data multi-season ABAP data downloaded using \code{\link{getAbapData}}. 10 | #' @param pentads an `sf` object returned by \code{\link{getRegionPentads}}. 11 | #' Defaults to `NULL`. 12 | #' 13 | #' @return an object of class \code{\link[unmarked]{unmarkedMultFrame}} 14 | #' 15 | #' @details In addition to reformatting the detection/non-detection ABAP data for 16 | #' use in `unmarked` and `ubms` occupancy models, this function also extracts two 17 | #' survey-level covariates: `hours` and `jday`. The `hours` variable is the total 18 | #' number of hours spent atlassing which is recorded on the pentad card and `jday` 19 | #' is the Julian day corresponding to the first day of atlassing for that card.\cr 20 | #' 21 | #' The function also adds the sampling year as a `yearlySiteCovs` which allows 22 | #' year to be used in the formula for colonization, extinction and detection 23 | #' probability.\cr 24 | #' 25 | #' If `pentads` are provided the `unmarked` frame will add the X and Y coordinates 26 | #' as site-level covariates (`siteCovs`). 27 | #' 28 | #' @note The processing time of `abapToUnmarked_multi` can be considerably long 29 | #' if the number of cards and pentads of the focal species is high, so patience 30 | #' may be required. 31 | 32 | #' 33 | #' @seealso \code{\link[unmarked]{colext}}, \code{\link[ubms]{stan_colext}} 34 | #' 35 | #' @author Dominic Henry \cr 36 | #' Pachi Cervantes 37 | #' 38 | #' @references 39 | #' MacKenzie, D. I., J. D. Nichols, J. E. Hines, M. G. Knutson, and A. B. 40 | #' Franklin. 2003. Estimating site occupancy, colonization, and local extinction 41 | #' when a species is detected imperfectly. Ecology 84:2200-2207. 42 | #' 43 | #' @export 44 | #' 45 | #' @examples 46 | #' \dontrun{ 47 | #' library(unmarked) 48 | #' abap_multi <- getAbapData(.spp = 212, 49 | #' .region_type = "province", 50 | #' .region = "Eastern Cape", 51 | #' .years = c(2009,2010,2011,2012)) 52 | #' 53 | #' abap_pentads <- getRegionPentads(.region_type = "province", 54 | #' .region = "Eastern Cape") 55 | #' 56 | #' ## Return unmarked frame no site covariates 57 | #' um_df <- abapToUnmarked_multi(abap_multi) 58 | #' summary(um_df) 59 | #' 60 | #' ## Return unmarked frame with Pentad coordinates as site covariates 61 | #' um_df <- abapToUnmarked_multi(abap_data = abap_multi, pentads = abap_pentads) 62 | #' summary(um_df) 63 | #' } 64 | abapToUnmarked_multi <- function(abap_data, pentads = NULL){ 65 | 66 | if(!requireNamespace("unmarked", quietly = TRUE)) { 67 | stop("Package unmarked doesn't seem to be installed. Please install before using this function.", 68 | call. = FALSE) 69 | } 70 | 71 | abap_data <- abap_data %>% 72 | dplyr::mutate(year = lubridate::year(StartDate)) 73 | 74 | years_vec <- abap_data %>% 75 | dplyr::pull(year) %>% 76 | unique() %>% 77 | sort() 78 | 79 | n_occasions <- length(years_vec) 80 | 81 | occasion_vec <- paste0(" 0", 1:n_occasions) 82 | 83 | pentad_id <- unique(abap_data$Pentad) 84 | 85 | n_sites <- length(pentad_id) 86 | 87 | max_visits <- abap_data %>% 88 | dplyr::count(Pentad, year) %>% 89 | dplyr::pull(n) %>% 90 | max() 91 | 92 | ## Extract spatial data 93 | if(!is.null(pentads)){ 94 | 95 | sf::st_agr(pentads) = "constant" 96 | 97 | pentad_xy <- pentads %>% 98 | dplyr::filter(pentad %in% pentad_id) %>% 99 | dplyr::arrange(pentad) %>% 100 | sf::st_centroid() %>% 101 | sf::st_coordinates() %>% 102 | as.data.frame() %>% 103 | dplyr::rename_all(tolower) 104 | 105 | } else { 106 | 107 | pentad_xy <- NULL 108 | } 109 | 110 | ## Create empty arrays 111 | Y <- array(NA, dim = c(n_sites, max_visits, n_occasions), 112 | dimnames = list(pentad_id, NULL, occasion_vec)) 113 | 114 | obs_hours <- array(NA, dim = c(n_sites, max_visits, n_occasions), 115 | dimnames = list(pentad_id, NULL, occasion_vec)) 116 | 117 | obs_jday <- array(NA, dim = c(n_sites, max_visits, n_occasions), 118 | dimnames = list(pentad_id, NULL, occasion_vec)) 119 | 120 | ## Populate detection/non-detection array (Y) and survey covariate arrays 121 | # Y[sites, visits, years] 122 | 123 | # Aux pentad column to join yearly results 124 | pentad_col <- abap_data %>% 125 | dplyr::group_by(Pentad) %>% 126 | dplyr::summarise(Pentad = unique(Pentad)) %>% 127 | dplyr::arrange(Pentad) 128 | 129 | 130 | # Aux padding vector 131 | vpad <- rep(NA, max_visits) 132 | 133 | for(k in seq_along(years_vec)){ 134 | 135 | ## Create dataframe to format 136 | year_data <- abap_data %>% 137 | dplyr::filter(year == years_vec[k]) %>% 138 | dplyr::select(Pentad, Spp, TotalHours, StartDate) %>% 139 | dplyr::mutate(Spp = ifelse(Spp == "-", 0L, 1L), 140 | julian_day = lubridate::yday(StartDate)) %>% 141 | dplyr::right_join(pentad_col, by = "Pentad") %>% # Join in Pentads missing for the year 142 | dplyr::nest_by(Pentad) %>% 143 | dplyr::arrange(Pentad) %>% 144 | dplyr::mutate(hourpad = list(head(c(data$TotalHours, vpad), max_visits)), 145 | jdaypad = list(head(c(data$julian_day, vpad), max_visits))) 146 | 147 | # Join in Pentads missing for the year 148 | # year_data <- pentad_col %>% 149 | # dplyr::left_join(year_data, by = "Pentad") 150 | 151 | ## Extract detection histories 152 | det_hist <- year_data %>% 153 | dplyr::mutate(dets = list(head(c(data$Spp, vpad), max_visits))) %>% 154 | dplyr::select(Pentad, dets) 155 | 156 | Y[,,k] <- do.call("rbind", det_hist$dets) 157 | 158 | ## Extract total hours 159 | obs_hours[,,k] <- do.call("rbind", year_data$hourpad) 160 | 161 | ## Extract Julian day 162 | obs_jday[,,k] <- do.call("rbind", year_data$jdaypad) 163 | 164 | } 165 | 166 | ## Convert 3 dimensional array to matrix format 167 | Y <- matrix(Y, n_sites, max_visits*n_occasions, 168 | dimnames = list(pentad_col$Pentad, NULL)) 169 | 170 | obs_hours <- matrix(obs_hours, n_sites, max_visits*n_occasions, 171 | dimnames = list(pentad_col$Pentad, NULL)) 172 | 173 | obs_jday <- matrix(obs_jday, n_sites, max_visits*n_occasions, 174 | dimnames = list(pentad_col$Pentad, NULL)) 175 | 176 | ## Create year occasion variable 177 | year <- matrix(occasion_vec, nrow(Y), n_occasions, byrow = TRUE) 178 | 179 | ## Create multi-season unmarked data frame 180 | umf_abap <- unmarked::unmarkedMultFrame(y = Y, 181 | obsCovs = list(hours = obs_hours, 182 | jday = obs_jday), 183 | siteCovs = pentad_xy, 184 | yearlySiteCovs = list(year = year), 185 | numPrimary = n_occasions) 186 | 187 | return(umf_abap) 188 | } 189 | -------------------------------------------------------------------------------- /R/addEEtoUnmarked_single.R: -------------------------------------------------------------------------------- 1 | #' Add Google Earth Engine covariate data to a single-season Unmarked frame 2 | #' 3 | #' @description Google Earth Engine (GEE) data for each pentad can be extracted to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} functions. `addEEtoUnmarked_single` can then be used to add these types of data to a single-season Unmarked frame. GEE data can subsquently be used as covariates in single-season occupancy models such as \code{\link[unmarked]{occu}}, \code{\link[unmarked]{occuRN}}, \code{\link[ubms]{stan_occu}} or \code{\link[ubms]{stan_occuRN}}. 4 | #' 5 | #' @param umf a single-season Unmarked frame containing ABAP detection/non-detection data returned by \code{\link{abapToUnmarked_single}}. 6 | #' @param ee_data a data frame with GEE data extracted using \code{\link{addVarEEcollection}} or \code{\link{addVarEEimage}}. The data frame needs to contain a column called `pentads` with the pentad ID from data extracted using the GEE functions. The remaining columns should only contain the GEE covariate values that are intended to be added to the `unmarked` frame. For ease of use in occupancy model formula notation it's recommended that the variable names in the data frame are concise and informative, and don't contain spaces. See the example below for how to create this data frame after extracting GEE data. 7 | #' 8 | #' @return an object of class \code{\link[unmarked]{unmarkedFrameOccu}} with survey and site covariates. 9 | #' 10 | #' @note The numeric ranges of various GEE data can be vastly different so it is advised that you scale your covariate data before running an occupancy model. This can be done within the formula notation of the various \code{\link[unmarked]{occu}} functions. 11 | #' 12 | #' @seealso \code{\link{abapToUnmarked_single}}, \code{\link{addVarEEimage}}, \code{\link{addVarEEcollection}} 13 | #' 14 | #' @author Dominic Henry \cr 15 | #' Pachi Cervantes 16 | #' 17 | #' @export 18 | #' 19 | #' @examples 20 | #' \dontrun{ 21 | #' library(rgee) 22 | #' library(ABDtools) 23 | #' library(unmarked) 24 | #' library(dplyr) 25 | #' 26 | #' ## Extract ABAP pentad data 27 | #' abap_pentads <- getRegionPentads(.region_type = "province", 28 | #' .region = "Eastern Cape") 29 | #' 30 | #' ## Extract single season ABAP bird data 31 | #' abap_single <- getAbapData(.spp_code = 212, 32 | #' .region_type = "province", 33 | #' .region = "Eastern Cape", 34 | #' .years = 2012) 35 | #' 36 | #' ## Create unmarked frame (with X & Y coords as site covariates) 37 | #' umf_single <- abapToUnmarked_single(abap_single, abap_pentads) 38 | #' summary(umf_single) 39 | #' 40 | #' ## Start up GEE 41 | #' ee_check() 42 | #' ee_Initialize(drive = TRUE) 43 | #' 44 | #' ## Create assetId for pentads of interest 45 | #' assetId <- sprintf("%s/%s", ee_get_assethome(), 'EC_pentads') 46 | #' 47 | #' ## Upload to pentads to GEE (only run this once per asset) 48 | #' uploadFeaturesToEE(pentads = abap_pentads, 49 | #' asset_id = assetId, 50 | #' load = FALSE) 51 | #' 52 | #' ## Load the remote asset into R session 53 | #' pentads <- ee$FeatureCollection(assetId) 54 | #' 55 | #' ## Extract spatial mean NDVI for each pentad 56 | #' ndvi_mean <- addVarEEcollection(ee_pentads = pentads, 57 | #' collection = "MODIS/006/MOD13A2", 58 | #' dates = c("2010-01-01", "2013-01-01"), 59 | #' temp_reducer = "mean", 60 | #' spt_reducer = "mean", 61 | #' bands = "NDVI") 62 | #' 63 | #' ## Extract spatial standard deviation of NDVI for each pentad 64 | #' ndvi_sd <- addVarEEcollection(ee_pentads = pentads, 65 | #' collection = "MODIS/006/MOD13A2", 66 | #' dates = c("2010-01-01", "2013-01-01"), 67 | #' temp_reducer = "mean", 68 | #' spt_reducer = "stdDev", 69 | #' bands = "NDVI") 70 | #' 71 | #' ## Extract spatial minimum land surface temperature for each pentad 72 | #' lst_min <- addVarEEcollection(ee_pentads = pentads, 73 | #' collection = "MODIS/061/MOD11A1", 74 | #' dates = c("2010-01-01", "2011-01-01"), 75 | #' temp_reducer = "mean", 76 | #' spt_reducer = "min", 77 | #' bands = "LST_Day_1km") 78 | #' 79 | #' ## Extract spatial maximum land surface temperature for each pentad 80 | #' lst_max <- addVarEEcollection(ee_pentads = pentads, 81 | #' collection = "MODIS/061/MOD11A1", 82 | #' dates = c("2010-01-01", "2011-01-01"), 83 | #' temp_reducer = "mean", 84 | #' spt_reducer = "max", 85 | #' bands = "LST_Day_1km") 86 | #' 87 | #' ## Create a site covariate data frame for input into addEEtoUnmarked_single(). 88 | #' ## Note the first column is called "pentad" which is a requirement for the function to work properly. 89 | #' my_ee_data <- bind_cols(pentad = ndvi_mean$pentad, 90 | #' ndvi_SD = ndvi_sd$NDVI_stdDev, 91 | #' ndvi_MEAN = ndvi_mean$NDVI_mean, 92 | #' temp_MIN = lst_min$LST_Day_1km_min, 93 | #' temp_MAX = lst_max$LST_Day_1km_max) 94 | #' 95 | #' ## Add GEE covariates to unmarked frame 96 | #' umf_single_ee <- addEEtoUnmarked_single(umf = umf_single, 97 | #' ee_data = my_ee_data) 98 | #' summary(umf_single_ee) 99 | #' 100 | #' ## A slightly different example: 101 | #' ## Annotate ABAP data with multiple bands from a GEE collection 102 | #' pentads_tc <- addVarEEcollection(ee_pentads = pentads, 103 | #' collection = "IDAHO_EPSCOR/TERRACLIMATE", 104 | #' dates = c("2010-01-01", "2011-01-01"), 105 | #' temp_reducer = "mean", 106 | #' spt_reducer = "mean", 107 | #' bands = c("tmmx", "tmmn")) 108 | #' 109 | #' ## Select the variables to transfer to the unmarked frame, making sure 110 | #' ## 'pentad' is amongst them 111 | #' my_ee_data <- pentads_tc %>% 112 | #' select(pentad, tmmx_mean, tmmn_mean) 113 | #' 114 | #' ## Add GEE covariates to unmarked frame 115 | #' umf_single_ee <- addEEtoUnmarked_single(umf = umf_single, 116 | #' ee_data = my_ee_data) 117 | #' 118 | #' summary(umf_single_ee) 119 | #' 120 | #' } 121 | 122 | addEEtoUnmarked_single <- function(umf, ee_data) { 123 | 124 | if(!requireNamespace("unmarked", quietly = TRUE)) { 125 | stop("Package unmarked doesn't seem to be installed. Please install before using this function.", 126 | call. = FALSE) 127 | } 128 | 129 | if(isFALSE("pentad" %in% names(ee_data))){ 130 | stop("ee_data does not contain the required 'pentad' variable. See function documentation.") 131 | } 132 | 133 | umf_pentads <- dimnames(umf@y)[[1]] 134 | 135 | site_cov <- ee_data %>% 136 | as.data.frame() %>% 137 | dplyr::select(-dplyr::any_of("geometry")) %>% 138 | dplyr::filter(pentad %in% umf_pentads) %>% 139 | dplyr::arrange(match(pentad, umf_pentads)) 140 | 141 | # check that pentads in unmarked data and covariate data are the same 142 | if(!identical(site_cov$pentad, umf_pentads)){ 143 | stop("Pentads in unmarked data and covariate data don't match") 144 | } 145 | 146 | site_cov <- site_cov %>% 147 | dplyr::select(-pentad) 148 | 149 | if (is.null(umf@siteCovs)) { 150 | umf@siteCovs <- site_cov 151 | } else { 152 | umf@siteCovs <- dplyr::bind_cols(umf@siteCovs, site_cov) 153 | } 154 | 155 | return(umf) 156 | } 157 | -------------------------------------------------------------------------------- /R/abapToSpOcc_multi.R: -------------------------------------------------------------------------------- 1 | #' ABAP to spOccupancy (multi-season) 2 | #' 3 | #' @description This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 4 | #' into an list which can be used to fit single-species occupancy models using 5 | #' \code{\link[spOccupancy]{spPGOcc}} (spatial) or \code{\link[spOccupancy]{PGOcc}} 6 | #' (non-spatial). The `spOccupancy` package fits single-species, multi-species, 7 | #' and integrated non-spatial and spatial occupancy models using Markov Chain Monte Carlo (MCMC). 8 | #' 9 | #' @param abap_data multi-season ABAP data downloaded using \code{\link{getAbapData}}. 10 | #' @param pentads an `sf` object returned by \code{\link{getRegionPentads}}. Defaults to `NULL`. 11 | #' @param proj_coords logical value indicating whether pentad coordinates are 12 | #' projected (`TRUE`) or kept in decimal degree format (`FALSE`). Defaults to `TRUE`. 13 | #' See details below for coordinate reference system used during transformation. 14 | #' @param seasons string indicating the name of the variable in `abap_data` that should 15 | #' be used to define seasons in multi-season models. 16 | #' 17 | #' @return A list containing data necessary for model fitting in `spOccupancy`. 18 | #' List elements are `y` (detection/non-detection data), `det.covs` (survey-level covariates), 19 | #' and `coords` (x and y centroids of pentads if spatial data are supplied). 20 | #' 21 | #' @details The \code{\link[spOccupancy]{spPGOcc}} function takes `coords` as an 22 | #' argument with X and Y coordinates included for each site. Within the context 23 | #' of ABAP, these `coords` are the centroid of each sampling pentad. In order to 24 | #' provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 25 | #' and provide the same inputs for `.region_type` and `.region` that are specified 26 | #' in corresponding \code{\link{getAbapData}} call. If proj_coords is set to `TRUE` 27 | #' then the coordinates will be transformed using the African Albers Equal Area 28 | #' coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 29 | #' for details). This projection is best suited for land masses extending in an 30 | #' east-to-west orientation at mid-latitudes making it suitable for projecting 31 | #' pentads in Southern Africa. The functions in the `spOccupancy` package assume 32 | #' that coordinates are projected so for best results it is recommended to always 33 | #' project the data. \cr 34 | #' 35 | #' If `pentads` are specified then the output can be automatically used in 36 | #' \code{\link[spOccupancy]{stPGOcc}}. If no spatial data are provided the output 37 | #' can be used in \code{\link[spOccupancy]{tPGOcc}}.\cr 38 | #' 39 | #' In addition to reformatting the detection/non-detection ABAP data for use in 40 | #' `spOccupancy` occupancy models, this function also extracts two survey-level 41 | #' covariates and adds them to the output list: ` hours` and `jday`. The `hours` 42 | #' variable is the total number of hours spent atlassing which is recorded on the 43 | #' pentad card and `jday` is the Julian day corresponding to the first day of 44 | #' atlassing for that card. 45 | #' 46 | #' 47 | #' @author Dominic Henry \cr 48 | #' Pachi Cervantes 49 | #' @seealso \code{\link[spOccupancy]{stPGOcc}}, \code{\link[spOccupancy]{tPGOcc}} 50 | #' @export 51 | #' 52 | #' @examples 53 | #' abap_data <- getAbapData(.spp_code = 212, 54 | #' .region_type = "province", 55 | #' .region = "Eastern Cape", 56 | #' .years = 2012:2014) 57 | #' 58 | #' abap_pentads <- getRegionPentads(.region_type = "province", 59 | #' .region = "Eastern Cape") 60 | #' # We will use years as occupancy reference seasons 61 | #' abap_data$year <- format(abap_data$StartDate, "%Y") 62 | #' 63 | #' ## Return list for spatial occupancy model 64 | #' stOcc <- abapToSpOcc_multi(abap_data, abap_pentads, seasons = "year") 65 | #' str(stOcc) 66 | #' 67 | #' ## Return list for spatial occupancy model (without coordinate projection) 68 | #' stOcc <- abapToSpOcc_multi(abap_data, abap_pentads, proj_coords = FALSE, "year") 69 | #' str(stOcc) 70 | #' 71 | #' ## List for non-spatial occupancy model 72 | #' tOcc <- abapToSpOcc_multi(abap_data, seasons = "year") 73 | #' str(tOcc) 74 | #' 75 | #' 76 | abapToSpOcc_multi <- function(abap_data, pentads = NULL, proj_coords = TRUE, seasons = NULL){ 77 | 78 | if(!requireNamespace("spOccupancy", quietly = TRUE)) { 79 | warning("Package spOccupancy doesn't seem to be installed. We recommend installing it if you are using this function.") 80 | } 81 | 82 | # Sort data frame for consistency with other functions 83 | abap_data <- abap_data %>% 84 | dplyr::arrange(Pentad, StartDate) 85 | 86 | # Extract unique pentads 87 | pentad_id <- sort(unique(abap_data$Pentad)) 88 | n_sites <- length(pentad_id) 89 | 90 | # Extract maximum number of visits in a single season 91 | if(is.null(seasons)){ 92 | 93 | warning("Argument 'seasons' not specified, so assuming a single season. 94 | Would you rather use abapToSpOcc_single()?") 95 | max_visits <- abap_data %>% 96 | dplyr::count(Pentad) %>% 97 | dplyr::pull(n) %>% 98 | max() 99 | 100 | n_seasons <- 1 101 | season_vec <- NULL 102 | 103 | } else { 104 | 105 | # Extract seasons and calculate max number of visits per season 106 | abap_data <- abap_data %>% 107 | dplyr::mutate(season = !!as.name(seasons)) 108 | 109 | season_vec <- abap_data %>% 110 | dplyr::pull(season) %>% 111 | unique() %>% 112 | sort() 113 | 114 | n_seasons <- length(season_vec) 115 | 116 | max_visits <- abap_data %>% 117 | dplyr::count(Pentad, season) %>% 118 | dplyr::pull(n) %>% 119 | max() 120 | 121 | } 122 | 123 | 124 | ## Create empty arrays 125 | Y <- array(NA, dim = c(n_sites, n_seasons, max_visits), 126 | dimnames = list(pentad_id, season_vec, seq_len(max_visits))) 127 | 128 | obs_hours <- array(NA, dim = c(n_sites, n_seasons, max_visits), 129 | dimnames = list(pentad_id, season_vec, seq_len(max_visits))) 130 | 131 | obs_jday <- array(NA, dim = c(n_sites, n_seasons, max_visits), 132 | dimnames = list(pentad_id, season_vec, seq_len(max_visits))) 133 | 134 | 135 | # Aux padding vector 136 | vpad <- rep(NA, max_visits) 137 | 138 | # Aux pentad column to join yearly results 139 | pentad_col <- abap_data %>% 140 | dplyr::distinct(Pentad) %>% 141 | dplyr::arrange(Pentad) 142 | 143 | for(k in seq_along(season_vec)){ 144 | 145 | ## Create dataframe to format 146 | season_data <- abap_data %>% 147 | dplyr::filter(season == season_vec[k]) %>% 148 | dplyr::select(Pentad, Spp, TotalHours, StartDate) %>% 149 | dplyr::mutate(Spp = ifelse(Spp == "-", 0L, 1L), 150 | julian_day = lubridate::yday(StartDate)) %>% 151 | dplyr::right_join(pentad_col, by = "Pentad") %>% # Join in Pentads missing for the year 152 | dplyr::nest_by(Pentad) %>% 153 | dplyr::arrange(Pentad) %>% 154 | dplyr::mutate(hourpad = list(head(c(data$TotalHours, vpad), max_visits)), 155 | jdaypad = list(head(c(data$julian_day, vpad), max_visits))) 156 | 157 | # Join in Pentads missing for the year 158 | # season_data <- pentad_col %>% 159 | # dplyr::left_join(season_data, by = "Pentad") 160 | 161 | ## Extract detection histories 162 | det_hist <- season_data %>% 163 | dplyr::mutate(dets = list(head(c(data$Spp, vpad), max_visits))) %>% 164 | dplyr::select(Pentad, dets) 165 | 166 | Y[,k,] <- do.call("rbind", det_hist$dets) 167 | 168 | ## Extract total hours 169 | obs_hours[,k,] <- do.call("rbind", season_data$hourpad) 170 | 171 | ## Extract Julian day 172 | obs_jday[,k,] <- do.call("rbind", season_data$jdaypad) 173 | 174 | } 175 | 176 | # Make data list 177 | if(is.null(seasons)){ 178 | spocc_data <- list(y = Y[,1,], 179 | det.covs = list(hours = obs_hours[,1,], jday = obs_jday[,1,])) 180 | } else { 181 | spocc_data <- list(y = Y, 182 | det.covs = list(hours = obs_hours, jday = obs_jday)) 183 | } 184 | 185 | 186 | ## Add spatial data if necessary 187 | if(!is.null(pentads)){ 188 | 189 | sf::st_agr(pentads) = "constant" 190 | aeaproj <- "+proj=aea +lat_1=20 +lat_2=-23 +lat_0=0 +lon_0=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs" 191 | 192 | if(isTRUE(proj_coords)){ 193 | pentads <- sf::st_transform(pentads, aeaproj) 194 | } 195 | 196 | pentad_xy <- pentads %>% 197 | dplyr::filter(pentad %in% pentad_id) %>% 198 | dplyr::arrange(pentad) %>% 199 | sf::st_centroid() %>% 200 | sf::st_coordinates() 201 | 202 | spocc_data <- list(y = Y, 203 | coords = pentad_xy, 204 | det.covs = list(hours = obs_hours, jday = obs_jday)) 205 | 206 | } 207 | 208 | return(spocc_data) 209 | 210 | } 211 | -------------------------------------------------------------------------------- /man/addEEtoUnmarked_multi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/addEEtoUnmarked_multi.R 3 | \name{addEEtoUnmarked_multi} 4 | \alias{addEEtoUnmarked_multi} 5 | \title{Add Google Earth Engine covariate data to a multi-season Unmarked frame} 6 | \usage{ 7 | addEEtoUnmarked_multi(umf, ee_assign, ee_data) 8 | } 9 | \arguments{ 10 | \item{umf}{a multi-season \code{unmarked} frame containing ABAP detection/non-detection 11 | data returned by \code{\link{abapToUnmarked_multi}}.} 12 | 13 | \item{ee_assign}{"site" if the covariate only varies between sites or "site-year" 14 | if the covariate varies across sites and between years.} 15 | 16 | \item{ee_data}{if \code{ee_assign} = "site" then a user-formatted data frame with 17 | GEE data extracted using \code{\link{addVarEEcollection}} or \code{\link{addVarEEimage}}. 18 | If \code{ee_assign} = "site-year" then the input is user-formatted list where each 19 | element contains a GEE variable that varies across years. See details below 20 | for the formatting requirements of \code{ee_data}.} 21 | } 22 | \value{ 23 | an object of class \code{\link[unmarked]{unmarkedMultFrame}} with 24 | survey, site, and site-year covariates. 25 | } 26 | \description{ 27 | Google Earth Engine (GEE) data for each pentad can be extracted 28 | to a data frame using ABAP's \code{\link{addVarEEcollection}} and \code{\link{addVarEEimage}} 29 | functions. \code{addEEtoUnmarked_multi} can then be used to add these types of 30 | data to a multi-season Unmarked frame. In multi-season (dynamic) occupancy 31 | models, the GEE data can either be used as covariates that vary at the site 32 | (\code{siteCovs}) level or covariates that vary at the site-year level (\code{yearlySiteCovs}). 33 | More information on this data structure can be found by looking at 34 | \code{\link[unmarked]{unmarkedMultFrame}}. 35 | } 36 | \details{ 37 | The data frame used when \code{ee_assign} = "site" needs to contain a 38 | column called \code{pentads} with the pentad ID from data extracted using the GEE 39 | functions. The remaining columns should only contain the GEE covariate values 40 | that are intended to be added to the \code{unmarked} frame. For ease of use in 41 | occupancy model formula notation it's recommended that the variable names 42 | in the data frame are concise and informative, and don't contain spaces. \cr 43 | 44 | Each element in the list used when \code{ee_assign} = "site-year" is a data frame 45 | that needs to have a column called \code{pentads} with the pentad ID followed by a 46 | GEE variable column for each year (primary survey period) defined in the 47 | \code{\link{abapToUnmarked_multi}} call. \cr 48 | 49 | See the examples below for how to create these data frame and list \code{ee_data} 50 | objects after extracting GEE data. 51 | } 52 | \note{ 53 | The numeric ranges of various GEE data can be vastly different so it 54 | is advised that you scale your covariate data before running an occupancy 55 | model. This can be done within the formula notation of the \code{\link[unmarked]{colext}} 56 | function. Note that \code{year} is automatically added as a site-year covariate 57 | in order to model changes in colonisation/extinction purely as a function of 58 | year (in terms of notation, the first year is coded as \code{01}, the second year 59 | as \code{02}, etc). 60 | } 61 | \examples{ 62 | \dontrun{ 63 | ## rgee and ABDtools are required to annotate data with Google Earth Engine 64 | library(rgee) 65 | library(ABDtools) 66 | library(unmarked) 67 | library(dplyr) 68 | 69 | ## Extract ABAP pentad data 70 | abap_pentads <- getRegionPentads(.region_type = "province", 71 | .region = "Eastern Cape") 72 | 73 | ## Extract multi-season ABAP bird data 74 | abap_multi <- getAbapData(.spp = 212, 75 | .region_type = "province", 76 | .region = "Eastern Cape", 77 | .years = c(2009,2010,2011,2012)) 78 | 79 | ## Create unmarked frame (with X & Y coords as site covariates) 80 | umf_multi <- abapToUnmarked_multi(abap_multi, abap_pentads) 81 | summary(umf_multi) 82 | 83 | ## Start up GEE 84 | ee_check() 85 | ee_Initialize(drive = TRUE) 86 | 87 | ## Create assetId for pentads of interest 88 | assetId <- file.path(ee_get_assethome(), 'EC_pentads') 89 | 90 | ## Upload to pentads to GEE (only run this once per asset) 91 | uploadFeaturesToEE(pentads = abap_pentads, 92 | asset_id = assetId, 93 | load = FALSE) 94 | 95 | ## Load the remote asset into R session 96 | pentads <- ee$FeatureCollection(assetId) 97 | 98 | ### ADD SITE-YEAR VARIABLES ### 99 | 100 | ## Create a multi-band image with mean NDVI for each year 101 | ndvi_multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 102 | dates = c("2009-01-01", "2012-12-31"), 103 | band = "NDVI", 104 | group_type = "year", 105 | groups = 2009:2012, 106 | reducer = "mean", 107 | unmask = FALSE) 108 | 109 | ## Find mean and standard deviation of NDVI value for each pentad and year from the multi-band image 110 | ndvi_mean <- addVarEEimage(pentads, ndvi_multiband, "mean") 111 | ndvi_sd <- addVarEEimage(pentads, ndvi_multiband, "stdDev") 112 | 113 | ## Format the data to include the pentad column and GEE values for each year 114 | ndvi_mean <- ndvi_mean \%>\% 115 | select(pentad, paste0("NDVI_", as.character(2009:2012))) 116 | 117 | ndvi_sd <- ndvi_sd \%>\% 118 | select(pentad, paste0("NDVI_", as.character(2009:2012))) 119 | 120 | ## Create a list where each named element is a multi-season GEE variable which can then be used in addEEtoUnmarked_multi() 121 | ee_siteyear <- list(ndvi_mean = ndvi_mean, 122 | ndvi_SD = ndvi_sd) 123 | 124 | ## Add GEE site-year data to unmarked frame 125 | umf_multi_ee1 <- addEEtoUnmarked_multi(umf_multi, 126 | ee_assign = "site-year", 127 | ee_siteyear) 128 | 129 | summary(umf_multi_ee1) 130 | 131 | ### ADD SITE VARIABLES ### 132 | 133 | ## Extract spatial minimum land surface temperature for each pentad 134 | lst_min <- addVarEEcollection(ee_feats = pentads, 135 | collection = "MODIS/061/MOD11A1", 136 | dates = c("2010-01-01", "2012-12-31"), 137 | temp_reducer = "mean", 138 | spt_reducer = "min", 139 | bands = "LST_Day_1km") 140 | 141 | ## Extract spatial maximum land surface temperature for each pentad 142 | lst_max <- addVarEEcollection(ee_feats = pentads, 143 | collection = "MODIS/061/MOD11A1", 144 | dates = c("2010-01-01", "2012-12-31"), 145 | temp_reducer = "mean", 146 | spt_reducer = "max", 147 | bands = "LST_Day_1km") 148 | 149 | ## Create a site covariate data frame for input into addEEtoUnmarked_multi(). 150 | ## Again, note the first column is called "pentad" which is a requirement for 151 | ## the function to work properly. 152 | ee_site <- bind_cols(pentad = lst_min$pentad, 153 | temp_MIN = lst_min$LST_Day_1km_min, 154 | temp_MAX = lst_max$LST_Day_1km_max) 155 | 156 | ## Add GEE site data to unmarked frame 157 | umf_multi_ee2 <- addEEtoUnmarked_multi(umf_multi, 158 | ee_assign = "site", 159 | ee_site) 160 | 161 | summary(umf_multi_ee2) 162 | 163 | ## Add GEE site-year data to the unmarked frame that already has site data 164 | ## (using addEEtoUnmarked_multi, site-year or site only data can be added sequentially). 165 | umf_multi_ee3 <- addEEtoUnmarked_multi(umf_multi_ee2, 166 | ee_assign = "site-year", 167 | ee_siteyear) 168 | 169 | summary(umf_multi_ee3) 170 | 171 | ## A slightly different example: 172 | ## Annotate ABAP data with multiple bands from a GEE collection 173 | pentads_tc <- addVarEEcollection(ee_pentads = pentads, 174 | collection = "IDAHO_EPSCOR/TERRACLIMATE", 175 | dates = c("2010-01-01", "2011-01-01"), 176 | temp_reducer = "mean", 177 | spt_reducer = "mean", 178 | bands = c("tmmx", "tmmn")) 179 | 180 | ## Select the variables to transfer to the unmarked frame, making sure 181 | ## 'pentad' is amongst them 182 | ee_site_tc <- pentads_tc \%>\% 183 | select(pentad, tmmx_mean, tmmn_mean) 184 | 185 | ## Add GEE site data to unmarked frame 186 | umf_multi_ee4 <- addEEtoUnmarked_multi(umf_multi, 187 | ee_assign = "site", 188 | ee_site_tc) 189 | 190 | summary(umf_multi_ee4) 191 | } 192 | } 193 | \seealso{ 194 | \code{\link{abapToUnmarked_multi}}, \code{\link[ABDtools]{addVarEEimage}}, 195 | \code{\link[ABDtools]{addVarEEcollection}} 196 | } 197 | \author{ 198 | Dominic Henry \href{mailto:dominic.henry@gmail.com}{dominic.henry@gmail.com} \cr 199 | Pachi Cervantes 200 | } 201 | -------------------------------------------------------------------------------- /R/abapToOccuR.R: -------------------------------------------------------------------------------- 1 | #' ABAP to occuR 2 | #' 3 | #' @description This function transforms a raw ABAP data frame (returned by \code{\link{getAbapData}}) 4 | #' into an list which can be used to fit single-species occupancy models using 5 | #' the package \href{https://github.com/r-glennie/occuR}{occuR}. This package 6 | #' can fit non-linear effects, including spatial, temporal and spatio-temporal effects 7 | #' using splines. 8 | #' @param abap_data ABAP data downloaded using \code{\link{getAbapData}}. 9 | #' @param occasion A character string indicating the variable in `abap_data` 10 | #' that informs about the season (or occasion, as referred to in occuR). This must always 11 | #' be supplied, although it is really only important in the case of multi-season data. 12 | #' It is typically "year" but could be something else. 13 | #' @param pentads Optional, An `sf` object returned by \code{\link{getRegionPentads}}. Defaults to `NULL`. 14 | #' @param proj_coords logical value indicating whether pentad coordinates are 15 | #' projected (`TRUE`) or kept in decimal degree format (`FALSE`). Defaults to `TRUE`. 16 | #' See details below for coordinate reference system used during transformation. 17 | #' 18 | #' @return A list containing data necessary for model fitting in `occuR`. 19 | #' List elements are: visit_data, a data frame containing information about individual 20 | #' visits; site_data, a data frame containing information about sites and seasons. 21 | #' If `pentads` are given then the coordinates of the centroid of the pentads will be 22 | #' included in site_data. 23 | #' 24 | #' @details The \href{https://github.com/r-glennie/occuR}{occuR} package can 25 | #' fit spatial effects, for which we need the spatial location of our sites. Within the context 26 | #' of ABAP, these locations are the centroid of each sampling pentad. In order to 27 | #' provide these spatial data to this function, simply use \code{\link{getRegionPentads}} 28 | #' and provide the same inputs for `.region_type` and `.region` that are specified 29 | #' in corresponding \code{\link{getAbapData}} call. If proj_coords is set to `TRUE` 30 | #' then the coordinates will be transformed using the African Albers Equal Area 31 | #' coordinate system (see \href{https://spatialreference.org/ref/esri/africa-albers-equal-area-conic/}{here} 32 | #' for details). This projection is best suited for land masses extending in an 33 | #' east-to-west orientation at mid-latitudes making it suitable for projecting 34 | #' pentads in Southern Africa. \cr 35 | #' 36 | #' In addition to reformatting the detection/non-detection ABAP data for use in 37 | #' `occuR` occupancy models, this function also extracts two survey-level 38 | #' covariates and adds them to the output list: ` hours` and `jday`. The `hours` 39 | #' variable is the total number of hours spent atlassing which is recorded on the 40 | #' pentad card and `jday` is the Julian day corresponding to the first day of 41 | #' atlassing for that card. 42 | #' 43 | #' @export 44 | #' 45 | #' @examples 46 | #' \dontrun{ 47 | #' library(ABAP) 48 | #' library(rgee) 49 | #' library(ABDtools) 50 | #' library(dplyr) 51 | #' 52 | #' ## Download single-season ABAP data 53 | #' abap_data <- getAbapData(.spp_code = 212, 54 | #' .region_type = "province", 55 | #' .region = "Eastern Cape", 56 | #' .years = 2012) 57 | #' 58 | #' # Download ABAP site spatial data 59 | #' abap_pentads <- getRegionPentads(.region_type = "province", 60 | #' .region = "Eastern Cape") 61 | #' 62 | #' # We will use years as occupancy reference seasons 63 | #' abap_data$year <- format(abap_data$StartDate, "%Y") 64 | #' 65 | #' ## Return list for spatial occupancy model 66 | #' occur_data <- abapToOccuR(abap_data, occasion = "year", abap_pentads) 67 | #' str(occur_data) 68 | #' 69 | #' ## Return list for spatial occupancy model (without coordinate projection) 70 | #' occur_data <- abapToOccuR(abap_data, "year", abap_pentads, proj_coords = FALSE) 71 | #' str(occur_data) 72 | #' 73 | #' ## List for non-spatial occupancy model 74 | #' occur_data <- abapToOccuR(abap_data, "year") 75 | #' str(occur_data) 76 | #' 77 | #' ## Transform multi-season ABAP data into occuR data is just as easy 78 | #' abap_data <- getAbapData(.spp_code = 212, 79 | #' .region_type = "province", 80 | #' .region = "Eastern Cape", 81 | #' .years = 2012:2015) 82 | #' 83 | #' # We will use years as occupancy reference seasons 84 | #' abap_data$year <- format(abap_data$StartDate, "%Y") 85 | #' 86 | #' ## Return list for spatial occupancy model 87 | #' occur_data <- abapToOccuR(abap_data, occasion = "year", abap_pentads) 88 | #' str(occur_data) 89 | #' 90 | #' ### ADD SITE-YEAR VARIABLES ### 91 | #' 92 | #' ## Start up GEE 93 | #' ee_check() 94 | #' ee_Initialize(drive = TRUE) 95 | #' 96 | #' ## Create assetId for pentads of interest 97 | #' assetId <- file.path(ee_get_assethome(), 'EC_pentads') 98 | #' 99 | #' ## Upload to pentads to GEE (only run this once per asset) 100 | #' uploadFeaturesToEE(pentads = abap_pentads, 101 | #' asset_id = assetId, 102 | #' load = FALSE) 103 | #' 104 | #' ## Load the remote asset into R session 105 | #' pentads <- ee$FeatureCollection(assetId) 106 | #' 107 | #' ## Create a multi-band image with mean NDVI for each year 108 | #' ndvi_multiband <- EEcollectionToMultiband(collection = "MODIS/006/MOD13A2", 109 | #' dates = c("2012-01-01", "2015-12-31"), 110 | #' band = "NDVI", 111 | #' group_type = "year", 112 | #' groups = 2012:2015, 113 | #' reducer = "mean", 114 | #' unmask = FALSE) 115 | #' 116 | #' ## Find mean and standard deviation of NDVI value for each pentad and year from the multi-band image 117 | #' ndvi_mean <- addVarEEimage(pentads, ndvi_multiband, "mean") 118 | #' ndvi_sd <- addVarEEimage(pentads, ndvi_multiband, "stdDev") 119 | #' 120 | #' ## Format the data to include the pentad column and GEE values for each year 121 | #' ndvi_mean <- ndvi_mean %>% 122 | #' select(pentad, paste0("NDVI_", as.character(2012:2015))) 123 | #' 124 | #' ndvi_sd <- ndvi_sd %>% 125 | #' select(pentad, paste0("NDVI_", as.character(2012:2015))) 126 | #' 127 | #' ## occuR data have the structure of regular data frames (they are data tables, but 128 | #' ## behave very similarly), so there are many ways we can transfer covariate values from 129 | #' ## other data frame-like objects. Here, we will transfer the value of these variables 130 | #' ## with dplyr::left_join(), but first we need to give covariates a long format with tidyr 131 | #' ndvi_mean_long <- ndvi_mean %>% 132 | #' sf::st_drop_geometry() %>% 133 | #' tidyr::pivot_longer(-pentad, names_to = "year", values_to = "NDVI_mean") %>% 134 | #' mutate(year = gsub("NDVI_", "", year)) 135 | #' 136 | #' ndvi_sd_long <- ndvi_sd %>% 137 | #' sf::st_drop_geometry() %>% 138 | #' tidyr::pivot_longer(-pentad, names_to = "year", values_to = "NDVI_sd") %>% 139 | #' mutate(year = gsub("NDVI_", "", year)) 140 | #' 141 | #' # Transfer variables via join 142 | #' occur_data_ee <- occur_data$site %>% 143 | #' dplyr::left_join(ndvi_mean_long, by = c("pentad", "year")) %>% 144 | #' dplyr::left_join(ndvi_sd_long, by = c("pentad", "year")) 145 | #' 146 | #' summary(occur_data_ee) 147 | #' 148 | #' } 149 | 150 | abapToOccuR <- function(abap_data, occasion, pentads = NULL, proj_coords = TRUE){ 151 | 152 | # if(!requireNamespace("occuR", quietly = TRUE)) { 153 | # warning("Package occuR doesn't seem to be installed. We recommend installing it if you are using this function.") 154 | # } 155 | 156 | # Create visit data 157 | visit_data <- abap_data %>% 158 | dplyr::arrange(Pentad, StartDate) %>% 159 | dplyr::group_by(Pentad) %>% 160 | dplyr::mutate(site = dplyr::cur_group_id()) %>% 161 | dplyr::ungroup() 162 | 163 | visit_data <- visit_data %>% 164 | dplyr::group_by(!!rlang::sym(occasion)) %>% 165 | dplyr::group_by(occasion = dplyr::cur_group_id()) %>% 166 | dplyr::ungroup() 167 | 168 | visit_data <- visit_data %>% 169 | dplyr::group_by(site) %>% 170 | dplyr::mutate(visit = dplyr::row_number()) %>% 171 | dplyr::ungroup() 172 | 173 | visit_data <- visit_data %>% 174 | dplyr::mutate(obs = ifelse(Spp == "-", 0L, 1L)) 175 | 176 | 177 | # Create additional covariates (total observation hours and day of year) 178 | visit_data <- visit_data %>% 179 | dplyr::rename(hours = TotalHours) %>% 180 | dplyr::mutate(jday = lubridate::yday(StartDate)) 181 | 182 | # Select columns 183 | visit_data <- visit_data %>% 184 | dplyr::select(pentad = Pentad, !!rlang::sym(occasion), site, occasion, visit, obs, hours, jday) 185 | 186 | # Create site data 187 | site_data <- visit_data %>% 188 | dplyr::distinct(pentad, year, site, occasion) 189 | 190 | # Extract spatial data 191 | if(!is.null(pentads)){ 192 | 193 | pentad_id <- unique(abap_data$Pentad) 194 | 195 | sf::st_agr(pentads) = "constant" 196 | aeaproj <- "+proj=aea +lat_1=20 +lat_2=-23 +lat_0=0 +lon_0=25 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs" 197 | 198 | if(isTRUE(proj_coords)){ 199 | pentads <- sf::st_transform(pentads, aeaproj) 200 | } 201 | 202 | ids <- pentads %>% 203 | dplyr::filter(pentad %in% pentad_id) %>% 204 | dplyr::arrange(match(pentad, site_data$pentad)) %>% 205 | dplyr::pull(pentad) 206 | 207 | pentad_xy <- pentads %>% 208 | dplyr::filter(pentad %in% pentad_id) %>% 209 | dplyr::arrange(match(pentad, site_data$pentad)) %>% 210 | sf::st_centroid() %>% 211 | sf::st_coordinates() %>% 212 | as.data.frame() %>% 213 | dplyr::mutate(pentad = ids) 214 | 215 | site_data <- site_data %>% 216 | dplyr::left_join(pentad_xy, by = "pentad") 217 | 218 | } 219 | 220 | return(list(site = data.table::as.data.table(site_data), 221 | visit = data.table::as.data.table(visit_data))) 222 | 223 | } 224 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # ABAP 5 | 6 | 7 | 8 | [![R-CMD-check](https://github.com/AfricaBirdData/ABAP/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/AfricaBirdData/ABAP/actions/workflows/R-CMD-check.yaml) 9 | [![Codecov test 10 | coverage](https://codecov.io/gh/AfricaBirdData/ABAP/branch/main/graph/badge.svg)](https://app.codecov.io/gh/AfricaBirdData/ABAP?branch=main) 11 | 12 | 13 | This packages provides functionality to access, download, and manipulate 14 | data from the [African Bird Atlas Project](http://www.birdmap.africa/). 15 | It is possible to download these same data using the [ABAP 16 | API](api.birdmap.africa), but being able to pull these data straight 17 | into R, in a standard format, should make them more accessible, easier 18 | to analyse, and eventually make our analyses more reliable and 19 | reproducible. 20 | 21 | There is another package named 22 | [`CWAC`](https://github.com/AfricaBirdData/CWAC) that provides similar 23 | functionality, but now to download count data from the Coordinated 24 | Waterbird Counts project. In addition, there is a companion package the 25 | [`ABDtools`](https://github.com/AfricaBirdData/ABDtools) package, which 26 | adds the functionality necessary to annotate different data formats 27 | (points and polygons) with environmental information from the [Google 28 | Earth Engine data 29 | catalog](https://developers.google.com/earth-engine/datasets). 30 | 31 | ## INSTRUCTIONS TO INSTALL 32 | 33 | To install `ABAP` from GitHub using the 34 | [remotes](https://github.com/r-lib/remotes) package, run: 35 | 36 | ``` r 37 | install.packages("remotes") 38 | remotes::install_github("AfricaBirdData/ABAP") 39 | ``` 40 | 41 | ## DOWNLOAD ABAP DATA FOR A SPECIES 42 | 43 | A typical workflow entails defining a region and a species of interest, 44 | e.g. say we are interested in the occupancy of the African Black Duck in 45 | the North West province of South Africa: 46 | 47 | First find the ABAP code for the species: 48 | 49 | ``` r 50 | library(ABAP) 51 | library(sf) 52 | #> Linking to GEOS 3.10.2, GDAL 3.4.1, PROJ 8.2.1; sf_use_s2() is TRUE 53 | library(dplyr, warn.conflicts = FALSE) 54 | 55 | # We can search for all duck species 56 | ducks <- searchAbapSpecies("Duck") 57 | 58 | # Then we can extract the code we are interested in 59 | ducks[ducks$Common_species == "African Black", "Spp"] 60 | #> # A tibble: 1 × 1 61 | #> Spp 62 | #> 63 | #> 1 95 64 | ``` 65 | 66 | With our code (95) we can download the data recorded for the region of 67 | interest: 68 | 69 | ``` r 70 | my_det_data <- getAbapData(.spp_code = 95, .region_type = "province", .region = "North West") 71 | ``` 72 | 73 | Great, but we may be interested in detection data in a set of pentads 74 | that do not correspond to any particular region. What do we do then? 75 | Well, although `getAbapData()` allows you to download data from any one 76 | pentad, it is not advised to use this functionality to loop over a set 77 | of pentads (unless it is a small set). This is because the algorithm 78 | will create a query to the remote database for each pentad, resulting in 79 | a very slow process. 80 | 81 | There are two ways of making this process more efficient: 82 | 83 | ### A spatial subset 84 | 85 | One way to obtain data for a set of pentads is to download a larger 86 | region that contains our pentads of interest and then filter only those 87 | we are interested in. 88 | 89 | If we know the code for the pentads of interest we could just go ahead 90 | and filter our data. For demonstration purposes let’s subset ten random 91 | pentads in the North West province using the data we just downloaded. 92 | This pentad selection probably doesn’t make much sense, but hopefully it 93 | shows the point. 94 | 95 | ``` r 96 | set.seed(8476) 97 | 98 | pentads_sel <- unique(my_det_data$Pentad) %>% 99 | sample(10) 100 | 101 | # We can now subset those pentads from the original data 102 | det_data_sel <- my_det_data[my_det_data$Pentad %in% pentads_sel,] 103 | ``` 104 | 105 | However, what we usually have is some sort of polygon defining a region 106 | of interest. If we had an [sf](https://r-spatial.github.io/sf/) polygon, 107 | we could extract the pentads contained in the polygon with 108 | 109 | ``` r 110 | # We first download all in the North West province pentads (to match our 111 | # original selection above as a spatial object. 112 | nw_pentads <- getRegionPentads(.region_type = "province", .region = "North West") 113 | 114 | # Here I am just going to create a polygon randomly, but usually you have a polygon 115 | # that makes sense to you (possibly you would load it with something like 116 | # my_pol <- sf::read_sf("path/to/my/polygon.shp") or something similar) 117 | my_pol <- data.frame(lon = c(25.1, 27.1), 118 | lat = c(-27.2, -25.2)) %>% 119 | st_as_sf(coords = c("lon", "lat"), 120 | crs = 4326) %>% # this is WGS84 121 | st_bbox() %>% 122 | st_as_sfc() 123 | 124 | # Extract pentads within your polygon 125 | my_pentads <- nw_pentads[my_pol,] # Convenient way of sub-setting spatial objects! 126 | 127 | # Subset ABAP data that falls within your polygon 128 | det_data_sel <- my_det_data %>% 129 | filter(Pentad %in% my_pentads[,"pentad"]) 130 | 131 | # Plots 132 | plot(st_geometry(nw_pentads), axes = TRUE, lwd = 0.1, cex.axis = 0.7) 133 | plot(st_geometry(my_pentads), add = TRUE, col = "red", lwd = 0.1) 134 | plot(st_geometry(my_pol), add = TRUE, border = "yellow") 135 | ``` 136 | 137 | 138 | 139 | ### Use a pentad group 140 | 141 | If we specify “group” in the `.region` argument `getAbapData()` returns 142 | all records for a specific group of pentads. Now, groups of pentads must 143 | be first created from the birdmap.africa websites (e.g., or ). For this, 144 | you will need to create an account. Once logged in, you can create 145 | groups from the coverage menu. Then, these groups can be viewed from you 146 | home menu. The name of the group is the last part of the URL displayed 147 | in the browser’s navigation bar. For example, I created a group named 148 | “test_group”, and the URL for this group is 149 | `⁠https://kenya.birdmap.africa/coverage/group/xxxx_tst_grp`⁠. The group 150 | name th at we need to pass on to the `getAbapData()` function is 151 | `xxxx_tst_grp`, the last part of the URL, where xxxx is your citizen 152 | scientist number (provided when creating an account). 153 | 154 | ``` r 155 | # Assuming we have created a group named "test_group" with URL ending in 156 | # "xxxx_tst_grp" our getAbapData() call is 157 | my_data <- getAbapData(.spp_code = 95, .region_type = "group", .region = "xxxx_tst_grp") 158 | ``` 159 | 160 | ## DOWNLOAD ABAP DATA FOR MULTIPLE SPECIES 161 | 162 | At the moment, the process of downloading multi-species data with the 163 | `ABAP` package consists of combining visit data with card record data. 164 | This means we first need to: 165 | 166 | 1. Decide on a spatial and temporal selection of data, 167 | 2. Download detection data for any species (just as we saw above), 168 | 3. Extract all cards that correspond to the spatial and temporal 169 | selection we made 170 | 4. Loop through all card numbers, download the data associated with 171 | them, and combine 172 | 173 | For example, if we wanted to download all data for all species in the 174 | Limpopo region of South Africa for the years 2018 to 2020. 175 | 176 | ``` r 177 | # Download detection data for any species. These data contain the code for all 178 | # the cards submitted to the project, regardless of the species we download. 179 | sp_data <- getAbapData(.spp = 151, 180 | .region_type = "province", 181 | .region = "Limpopo", 182 | .years = 2018:2020, 183 | .adhoc = FALSE) 184 | 185 | 186 | # From these data we can extract the cards we are interested in. 187 | my_cards <- unique(sp_data$CardNo) 188 | 189 | # Now, this is the painful part, we need to download the data from all the cards 190 | # using a loop 191 | 192 | # Create an empty data frame 193 | card_data <- data.frame() 194 | 195 | # Loop through cards and download data 196 | for(i in seq_along(my_cards)){ 197 | 198 | dd <- getCardRecords(.CardNo = my_cards[i]) 199 | card_data <- bind_rows(card_data, dd) 200 | 201 | } 202 | 203 | # To finish up and get a complete data set, we could join the species data with 204 | # the card data (note that we remove species info from pentad data, because it is 205 | # related to the first species we selected "randomly") 206 | final_data <- full_join(pentad_data %>% 207 | select(-c("Spp", "Sequence", "Common_name", "Taxonomic_name")), 208 | card_data, 209 | by = "CardNo") 210 | ``` 211 | 212 | In the future we would like to make this process easier by allowing 213 | multi-card queries to the database, which would make the process much 214 | more efficient. But for now this is usable workaround. 215 | 216 | ## INSTRUCTIONS TO CONTRIBUTE CODE 217 | 218 | First clone the repository to your local machine: 219 | 220 | - In RStudio, create a new project 221 | - In the ‘Create project’ menu, select ‘Version Control’/‘Git’ 222 | - Copy the repository URL (click on the ‘Code’ green button and copy the 223 | link) 224 | - Choose the appropriate directory and ‘Create project’ 225 | - Remember to pull the latest version regularly 226 | 227 | For site owners: 228 | 229 | There is the danger of multiple people working simultaneously on the 230 | project code. If you make changes locally on your computer and, before 231 | you push your changes, others push theirs, there might be conflicts. 232 | This is because the HEAD pointer in the main branch has moved since you 233 | started working. 234 | 235 | To deal with these lurking issues, I would suggest opening and working 236 | on a topic branch. This is a just a regular branch that has a short 237 | lifespan. In steps: 238 | 239 | - Open a branch at your local machine 240 | - Push to the remote repo 241 | - Make your changes in your local machine 242 | - Commit and push to remote 243 | - Create pull request: 244 | - In the GitHub repo you will now see an option that notifies of 245 | changes in a branch: click compare and pull request. 246 | - Delete the branch. When you are finished, you will have to delete the 247 | new branch in the remote repo (GitHub) and also in your local machine. 248 | In your local machine you have to use Git directly, because apparently 249 | RStudio doesn´t do it: 250 | - In your local machine, change to master branch. 251 | - Either use the Git GUI (go to branches/delete/select branch/push). 252 | - Or use the console typing ‘git branch -d your_branch_name’. 253 | - It might also be necessary to prune remote branches with ‘git remote 254 | prune origin’. 255 | 256 | Opening branches is quick and easy, so there is no harm in opening 257 | multiple branches a day. However, it is important to merge and delete 258 | them often to keep things tidy. Git provides functionality to deal with 259 | conflicting branches. More about branches here: 260 | 261 | 262 | 263 | Another idea is to use the ‘issues’ tab that you find in the project 264 | header. There, we can identify issues with the package, assign tasks and 265 | warn other contributors that we will be working on the code. 266 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%", 13 | eval = TRUE 14 | ) 15 | ``` 16 | 17 | # ABAP 18 | 19 | 20 | [![R-CMD-check](https://github.com/AfricaBirdData/ABAP/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/AfricaBirdData/ABAP/actions/workflows/R-CMD-check.yaml) 21 | [![Codecov test coverage](https://codecov.io/gh/AfricaBirdData/ABAP/branch/main/graph/badge.svg)](https://app.codecov.io/gh/AfricaBirdData/ABAP?branch=main) 22 | 23 | 24 | This packages provides functionality to access, download, and manipulate data from 25 | the [African Bird Atlas Project](http://www.birdmap.africa/). It is possible to 26 | download these same data using the [ABAP API](api.birdmap.africa), but being able 27 | to pull these data straight into R, in a standard format, should make them more 28 | accessible, easier to analyse, and eventually make our analyses more reliable and 29 | reproducible. 30 | 31 | There is another package named [`CWAC`](https://github.com/AfricaBirdData/CWAC) 32 | that provides similar functionality, but now to download count data from the 33 | Coordinated Waterbird Counts project. In addition, there is a companion package 34 | the [`ABDtools`](https://github.com/AfricaBirdData/ABDtools) package, which adds 35 | the functionality necessary to annotate different data formats (points and polygons) 36 | with environmental information from the 37 | [Google Earth Engine data catalog](https://developers.google.com/earth-engine/datasets). 38 | 39 | 40 | ## INSTRUCTIONS TO INSTALL 41 | 42 | To install `ABAP` from GitHub using the [remotes](https://github.com/r-lib/remotes) package, run: 43 | 44 | ```{r, eval = FALSE} 45 | install.packages("remotes") 46 | remotes::install_github("AfricaBirdData/ABAP") 47 | ``` 48 | 49 | ## DOWNLOAD ABAP DATA FOR A SPECIES 50 | 51 | A typical workflow entails defining a region and a species of interest, 52 | e.g. say we are interested in the occupancy of the African Black Duck in 53 | the North West province of South Africa: 54 | 55 | First find the ABAP code for the species: 56 | 57 | ```{r} 58 | library(ABAP) 59 | library(sf) 60 | library(dplyr, warn.conflicts = FALSE) 61 | 62 | # We can search for all duck species 63 | ducks <- searchAbapSpecies("Duck") 64 | 65 | # Then we can extract the code we are interested in 66 | ducks[ducks$Common_species == "African Black", "Spp"] 67 | 68 | ``` 69 | 70 | With our code (95) we can download the data recorded for the region of interest: 71 | 72 | ```{r} 73 | my_det_data <- getAbapData(.spp_code = 95, .region_type = "province", .region = "North West") 74 | ``` 75 | 76 | Great, but we may be interested in detection data in a set of pentads that do not 77 | correspond to any particular region. What do we do then? Well, although `getAbapData()` 78 | allows you to download data from any one pentad, it is not advised to use this 79 | functionality to loop over a set of pentads (unless it is a small set). 80 | This is because the algorithm will create a query to the remote database for each 81 | pentad, resulting in a very slow process. 82 | 83 | There are two ways of making this process more efficient: 84 | 85 | ### A spatial subset 86 | 87 | One way to obtain data for a set of pentads is to download a larger region that 88 | contains our pentads of interest and then filter only those we are interested in. 89 | 90 | If we know the code for the pentads of interest we could just go ahead and filter 91 | our data. For demonstration purposes let's subset ten random pentads in the North West 92 | province using the data we just downloaded. This pentad selection probably 93 | doesn't make much sense, but hopefully it shows the point. 94 | 95 | ```{r} 96 | set.seed(8476) 97 | 98 | pentads_sel <- unique(my_det_data$Pentad) %>% 99 | sample(10) 100 | 101 | # We can now subset those pentads from the original data 102 | det_data_sel <- my_det_data[my_det_data$Pentad %in% pentads_sel,] 103 | 104 | ``` 105 | 106 | However, what we usually have is some sort of polygon defining a region of interest. 107 | If we had an [sf](https://r-spatial.github.io/sf/) polygon, we 108 | could extract the pentads contained in the polygon with 109 | 110 | ```{r} 111 | # We first download all in the North West province pentads (to match our 112 | # original selection above as a spatial object. 113 | nw_pentads <- getRegionPentads(.region_type = "province", .region = "North West") 114 | 115 | # Here I am just going to create a polygon randomly, but usually you have a polygon 116 | # that makes sense to you (possibly you would load it with something like 117 | # my_pol <- sf::read_sf("path/to/my/polygon.shp") or something similar) 118 | my_pol <- data.frame(lon = c(25.1, 27.1), 119 | lat = c(-27.2, -25.2)) %>% 120 | st_as_sf(coords = c("lon", "lat"), 121 | crs = 4326) %>% # this is WGS84 122 | st_bbox() %>% 123 | st_as_sfc() 124 | 125 | # Extract pentads within your polygon 126 | my_pentads <- nw_pentads[my_pol,] # Convenient way of sub-setting spatial objects! 127 | 128 | # Subset ABAP data that falls within your polygon 129 | det_data_sel <- my_det_data %>% 130 | filter(Pentad %in% my_pentads[,"pentad"]) 131 | 132 | # Plots 133 | plot(st_geometry(nw_pentads), axes = TRUE, lwd = 0.1, cex.axis = 0.7) 134 | plot(st_geometry(my_pentads), add = TRUE, col = "red", lwd = 0.1) 135 | plot(st_geometry(my_pol), add = TRUE, border = "yellow") 136 | ``` 137 | 138 | ### Use a pentad group 139 | 140 | If we specify "group" in the `.region` argument `getAbapData()` returns all 141 | records for a specific group of pentads. Now, groups of pentads must be first 142 | created from the birdmap.africa websites (e.g., \href{https://sabap2.birdmap.africa/}{SABAP2} or 143 | \href{https://kenya.birdmap.africa/}{Kenya Bird Map}). For this, you will need 144 | to create an account. Once logged in, you can create groups from the coverage menu. 145 | Then, these groups can be viewed from you home menu. The name of the group is the 146 | last part of the URL displayed in the browser's navigation bar. For example, 147 | I created a group named "test_group", and the URL for this group is 148 | `⁠https://kenya.birdmap.africa/coverage/group/xxxx_tst_grp`⁠. The group name th 149 | at we need to pass on to the `getAbapData()` function is `xxxx_tst_grp`, the last 150 | part of the URL, where xxxx is your citizen scientist number (provided when creating an account). 151 | 152 | ```{r eval=FALSE} 153 | # Assuming we have created a group named "test_group" with URL ending in 154 | # "xxxx_tst_grp" our getAbapData() call is 155 | my_data <- getAbapData(.spp_code = 95, .region_type = "group", .region = "xxxx_tst_grp") 156 | 157 | ``` 158 | 159 | ## DOWNLOAD ABAP DATA FOR MULTIPLE SPECIES 160 | 161 | At the moment, the process of downloading multi-species data with the `ABAP` package 162 | consists of combining visit data with card record data. This means we first need to: 163 | 164 | 1. Decide on a spatial and temporal selection of data, 165 | 2. Download detection data for any species (just as we saw above), 166 | 3. Extract all cards that correspond to the spatial and temporal selection we made 167 | 4. Loop through all card numbers, download the data associated with them, and combine 168 | 169 | For example, if we wanted to download all data for all species in the Limpopo 170 | region of South Africa for the years 2018 to 2020. 171 | 172 | ```{r eval=FALSE} 173 | # Download detection data for any species. These data contain the code for all 174 | # the cards submitted to the project, regardless of the species we download. 175 | sp_data <- getAbapData(.spp = 151, 176 | .region_type = "province", 177 | .region = "Limpopo", 178 | .years = 2018:2020, 179 | .adhoc = FALSE) 180 | 181 | 182 | # From these data we can extract the cards we are interested in. 183 | my_cards <- unique(sp_data$CardNo) 184 | 185 | # Now, this is the painful part, we need to download the data from all the cards 186 | # using a loop 187 | 188 | # Create an empty data frame 189 | card_data <- data.frame() 190 | 191 | # Loop through cards and download data 192 | for(i in seq_along(my_cards)){ 193 | 194 | dd <- getCardRecords(.CardNo = my_cards[i]) 195 | card_data <- bind_rows(card_data, dd) 196 | 197 | } 198 | 199 | # To finish up and get a complete data set, we could join the species data with 200 | # the card data (note that we remove species info from pentad data, because it is 201 | # related to the first species we selected "randomly") 202 | final_data <- full_join(pentad_data %>% 203 | select(-c("Spp", "Sequence", "Common_name", "Taxonomic_name")), 204 | card_data, 205 | by = "CardNo") 206 | 207 | ``` 208 | 209 | In the future we would like to make this process easier by allowing multi-card 210 | queries to the database, which would make the process much more efficient. But 211 | for now this is usable workaround. 212 | 213 | 214 | ## INSTRUCTIONS TO CONTRIBUTE CODE 215 | 216 | First clone the repository to your local machine: 217 | 218 | - In RStudio, create a new project 219 | - In the ‘Create project’ menu, select ‘Version Control’/‘Git’ 220 | - Copy the repository URL (click on the ‘Code’ green button and 221 | copy the link) 222 | - Choose the appropriate directory and ‘Create project’ 223 | - Remember to pull the latest version regularly 224 | 225 | For site owners: 226 | 227 | There is the danger of multiple people working simultaneously on the 228 | project code. If you make changes locally on your computer and, before 229 | you push your changes, others push theirs, there might be conflicts. 230 | This is because the HEAD pointer in the main branch has moved since you 231 | started working. 232 | 233 | To deal with these lurking issues, I would suggest opening and working 234 | on a topic branch. This is a just a regular branch that has a short 235 | lifespan. In steps: 236 | 237 | - Open a branch at your local machine 238 | - Push to the remote repo 239 | - Make your changes in your local machine 240 | - Commit and push to remote 241 | - Create pull request: 242 | - In the GitHub repo you will now see an option that notifies of 243 | changes in a branch: click compare and pull request. 244 | - Delete the branch. When you are finished, you will have to delete the new 245 | branch in the remote repo (GitHub) and also in your local machine. In your 246 | local machine you have to use Git directly, because apparently RStudio 247 | doesn´t do it: 248 | - In your local machine, change to master branch. 249 | - Either use the Git GUI (go to branches/delete/select 250 | branch/push). 251 | - Or use the console typing ‘git branch -d your\_branch\_name’. 252 | - It might also be necessary to prune remote branches with 'git remote prune origin'. 253 | 254 | Opening branches is quick and easy, so there is no harm in opening 255 | multiple branches a day. However, it is important to merge and delete 256 | them often to keep things tidy. Git provides functionality to deal with 257 | conflicting branches. More about branches here: 258 | 259 | 260 | 261 | Another idea is to use the ‘issues’ tab that you find in the project 262 | header. There, we can identify issues with the package, assign tasks and 263 | warn other contributors that we will be working on the code. 264 | --------------------------------------------------------------------------------