Skip to content

Commit

Permalink
Add package setup and data retrieval
Browse files Browse the repository at this point in the history
  • Loading branch information
gmyenni committed May 3, 2022
1 parent 985817e commit 7f37b28
Show file tree
Hide file tree
Showing 17 changed files with 747 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
^wader\.Rproj$
^\.Rproj\.user$
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ vignettes/*.pdf

# R Environment Variables
.Renviron
.Rproj.user
46 changes: 46 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
> This is intended to be a general-purpose code of conduct for lab software projects, to facilitate interactions between the lab and outside contributors. Feel free to copy this file into the repo and delete this note.
# Contributor Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [[email protected]](mailto:[email protected]). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
33 changes: 33 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Package: wader
Title: A collection of functions to retrieve and summarize the EvergladesWadingBird Data
Version: 0.0.0.9000
Authors@R:
c(person(given = c("Glenda", "M."),
family = "Yenni",
role = c("aut", "cre"),
email = "[email protected]",
comment = c(ORCID = "0000-0001-6969-1848")))
Description: Download and generate summaries for the count,
nesting, indicator, and weather data from the Wading Bird Project.
The Wading Bird Project is a long-term (and ongoing) monitoring site
in the Everglades water conservation areas. The raw data files can be found at
<https://github.com/weecology/evergladeswadingbird>.
License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a
license
Depends:
R (>= 3.2.3)
Imports:
clipr,
clisymbols,
crayon,
dplyr,
httr,
lubridate,
magrittr,
rlang,
tidyr,
tidyselect (>= 1.0.0),
zoo
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.2
25 changes: 25 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by roxygen2: do not edit by hand

export(check_default_data_path)
export(check_for_newer_data)
export(download_observations)
export(get_default_data_path)
export(load_datafile)
export(load_indicator_data)
export(use_default_data_path)
importFrom(httr,GET)
importFrom(httr,content)
importFrom(httr,stop_for_status)
importFrom(lubridate,"%m+%")
importFrom(rlang,"!!!")
importFrom(rlang,"!!")
importFrom(rlang,":=")
importFrom(rlang,.data)
importFrom(stats,median)
importFrom(stats,na.omit)
importFrom(utils,download.file)
importFrom(utils,head)
importFrom(utils,read.csv)
importFrom(utils,read.table)
importFrom(utils,tail)
importFrom(utils,unzip)
280 changes: 280 additions & 0 deletions R/download_data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@



#' @title Download the EvergladesWadingBird repo
#'
#' @description Downloads specified version of the EvergladesWadingBird data.
#'
#' @param path Folder into which data will be downloaded
#'
#' @param version Version of the data to download (default = "latest").
#' If \code{NULL}, returns.
#'
#' @param quiet logical, whether to download data silently.
#'
#' @param verbose logical, whether to provide details of downloading.
#'
#' @param timeout Positive \code{integer} or integer \code{numeric} seconds for timeout on downloads. Temporarily overrides the \code{"timeout"} option in \code{\link[base]{options}}.
#'
#' @param from_zenodo logical; if `TRUE`, get info from Zenodo, otherwise GitHub
#'
#' @return NULL invisibly.
#'
#'
#' @export
#'
download_observations <- function(path = get_default_data_path(),
version = "latest",
from_zenodo = FALSE,
quiet = FALSE,
verbose = FALSE,
timeout = getOption("timeout")) {

if (is.null(version)) {

return(invisible())

}

timeout_backup <- getOption("timeout")
on.exit(options(timeout = timeout_backup))
options(timeout = timeout)

if (from_zenodo) {

base_url <- "https://zenodo.org/api/records/"

got <- GET(base_url, query = list(q = "conceptrecid:1215988",
size = 9999,
all_versions = "true"))

stop_for_status(got, task = paste0("locate Zenodo concept record"))

contents <- content(got)

metadata <- lapply(FUN = getElement,
X = contents,
name = "metadata")
versions <- sapply(FUN = getElement,
X = metadata,
name = "version")
pub_date <- sapply(FUN = getElement,
X = metadata,
name = "publication_date")

selected <- ifelse(version == "latest",
which.max(as.Date(pub_date)),
which(versions == version))

if (length(selected) == 0){

stop(paste0("Failed to locate version `", version, "`"))

}

zipball_url <- contents[[selected]]$files[[1]]$links$download
version <- ifelse(version == "latest",
metadata[[selected]]$version, version)

} else {

base_url <- "https://api.github.com/repos/weecology/EvergladesWadingBird/releases/"
url <- ifelse(version == "latest",
paste0(base_url, "latest"),
paste0(base_url, "tags/", version))

got <- GET(url)

stop_for_status(got, task = paste0("locate version `", version, "`"))

zipball_url <- content(got)$zipball_url

version <- ifelse(version == "latest", content(got)$name, version)
}


if (!quiet) {
message("Downloading version `", version, "` of the data...")
}

temp <- file.path(tempdir(), "EvergladesWadingBird.zip")
final <- file.path(path, "EvergladesWadingBird")

download.file(zipball_url, temp, quiet = !verbose, mode = "wb")
if (file.exists(final)) {

old_files <- list.files(final,
full.names = TRUE,
all.files = TRUE,
recursive = TRUE,
include.dirs = FALSE)

file.remove(normalizePath(old_files))

unlink(final, recursive = TRUE)

}

temp_unzip <- unzip(temp, list = TRUE)$Name[1]

unzip(temp, exdir = path)

Sys.sleep(10)

file.remove(temp)
file.rename(file.path(path, temp_unzip), final)

invisible()
}

#' @title Check for latest version of data files
#' @description Check the latest version against the data that exists on
#' the GitHub repo
#' @param path Folder in which data will be checked
#'
#' @return bool TRUE if there is a newer version of the data online
#'
#' @export
check_for_newer_data <- function (path = get_default_data_path()) {

tryCatch(
path <- file.path(path),
error = function(e) stop("Unable to locate ", path, call. = FALSE))

version_file <- file.path(path, "EvergladesWadingBird", "version.txt")

if (!file.exists(version_file)) {
return(TRUE)
}


url <- "https://api.github.com/repos/weecology/EvergladesWadingBird/releases/latest"
got <- tryCatch(GET(url),
error = function(e) NULL)
if (is.null(got)) {
return(FALSE)
}

stop_for_status(got, task = paste0("locate latest GitHub version"))

github_version_str <- content(got)$name


pattern <- "([0-9]+)\\.([0-9]+)\\.([0-9]+)"
version_str <- as.character(read.table(version_file)[1, 1])
local_version <- c(as.numeric(gsub(pattern, "\\1", version_str)),
as.numeric(gsub(pattern, "\\2", version_str)),
as.numeric(gsub(pattern, "\\3", version_str)))

github_version <- c(as.numeric(gsub(pattern, "\\1", github_version_str)),
as.numeric(gsub(pattern, "\\2", github_version_str)),
as.numeric(gsub(pattern, "\\3", github_version_str)))

if (github_version[1] > local_version[1])
return(TRUE)

if (github_version[1] == local_version[1] &&
github_version[2] > local_version[2])
return(TRUE)

if (github_version[1] == local_version[1] &&
github_version[2] == local_version[2] &&
github_version[3] > local_version[3])
return(TRUE)

return(FALSE)
}

#' @rdname use_default_data_path
#'
#' @description \code{check_default_data_path} checks if a default data path is
#' set, and prompts the user to set it if it is missing.
#'
#' @inheritParams use_default_data_path
#' @param MESSAGE_FUN the function to use to output messages
#' @param DATA_NAME the name of the dataset to use in output messages
#' @return FALSE if there is no path set, TRUE otherwise
#'
#' @export
#'
check_default_data_path <- function(ENV_VAR = "WADER_DATA_PATH",
MESSAGE_FUN = message, DATA_NAME = "EvergladesWadingBird data")
{
if (is.na(get_default_data_path(fallback = NA, ENV_VAR)))
{
MESSAGE_FUN("You don't appear to have a defined location for storing ", DATA_NAME, ".")
MESSAGE_FUN(format_todo(" Call ",
format_code('use_default_data_path(\"<path>\")'),
" if you wish to set the default data path."))
MESSAGE_FUN(DATA_NAME, " will be downloaded into ",
format_code(path.expand("~")), " otherwise.")
return(FALSE)
}
return(TRUE)
}

#' @rdname use_default_data_path
#'
#' @description \code{get_default_data_path} gets the value of the data path
#' environmental variable
#'
#' @inheritParams use_default_data_path
#' @param fallback the default value to use if the setting is missing
#'
#' @export
#'
get_default_data_path <- function(fallback = "~", ENV_VAR = "WADER_DATA_PATH")
{
Sys.getenv(ENV_VAR, unset = fallback)
}

#' @name use_default_data_path
#' @aliases get_default_data_path
#'
#' @title Manage the default path for downloading EvergladesWadingBird Data into
#'
#' @description \code{use_default_data_path} has 3 steps. First, it checks for
#' the presence of a pre-existing setting for the environmental variable.
#' Then it checks if the folder exists and creates it, if needed. Then it
#' provides instructions for setting the environmental variable.
#' @inheritParams download_observations
#' @param ENV_VAR the environmental variable to check (by default
#' `"WADER_DATA_PATH"``)
#'
#' @return None
#'
#' @export
use_default_data_path <- function(path = NULL, ENV_VAR = "WADER_DATA_PATH")
{
# check for preexisting setting
curr_data_path <- Sys.getenv(ENV_VAR, unset = NA)
if (!is.na(curr_data_path))
{
warning("A default data path exists:", Sys.getenv(ENV_VAR), ".")
}

# check if a path is provided
if (is.null(path))
{
stop("Please provide a path to store downloaded data.")
}

# check if path is valid
if (!dir.exists(path))
{
dir.create(path)
}

# display message and copy new path setting to clipboard
path_setting_string <- paste0(ENV_VAR, "=", '"', path, '"')
message(format_todo("Call ", format_code('usethis::edit_r_environ()'), " to open ",
format_value('.Renviron')))
message(format_todo("Store your data path with a line like:"))
message(" ", format_code(path_setting_string))
if (rlang::is_interactive() && clipr::clipr_available()) {
clipr::write_clip(path_setting_string)
message(" [Copied to clipboard]")
}
message(format_todo("Make sure ", format_value('.Renviron'), " ends with a newline!"))
return()
}
Loading

0 comments on commit 7f37b28

Please sign in to comment.