diff --git a/DESCRIPTION b/DESCRIPTION index 52012784..bbd6f6de 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,9 +1,11 @@ Package: etn Title: Access Data from the European Tracking Network -Version: 2.1.0 +Version: 2.2.0 Authors@R: c( + person("Pieter", "Huybrechts", email = "pieter.huybrechts@inbo.be", + role = c("aut", "cre"), comment = c(ORCID = "0000-0002-6658-6062")), person("Peter", "Desmet", email = "peter.desmet@inbo.be", - role = c("aut", "cre"), comment = c(ORCID = "0000-0002-8442-8025")), + role = "aut", comment = c(ORCID = "0000-0002-8442-8025")), person("Damiano", "Oldoni", email = "damiano.oldoni@inbo.be", role = "aut", comment = c(ORCID = "0000-0003-3445-7562")), person("Stijn", "Van Hoey", email = "stijnvanhoey@gmail.com", @@ -37,10 +39,13 @@ Suggests: kableExtra, knitr, rmarkdown, - testthat, - tidyr + testthat (>= 3.0.0), + tidyr, + frictionless, + withr LazyData: true Encoding: UTF-8 VignetteBuilder: knitr Roxygen: list(markdown = TRUE) -RoxygenNote: 7.2.2 +RoxygenNote: 7.2.3 +Config/testthat/edition: 3 diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 00000000..f65cea4e --- /dev/null +++ b/NEWS.md @@ -0,0 +1,20 @@ +# etn 2.2.0 + +* Add `NEWS.md` file to communicate changes to the package. +* Add `depth_in_meters` field to `get_acoustic_detections()` (#261). +* Fix issue in `download_acoustic_dataset()` where some fields were missing from `datapackage.json`. +* Stricter unit tests (#268). + +# etn 2.1.0 + +* Add funder and use default README.Rmd (#247). +* New function `write_dwc()` to transform acoustic telemetry data to Darwin Core that can be harvested by OBIS and GBIF (#257). + +# etn 2.0.0 + +This releases updates the package to make use of the new model and scope of ETN. Have a look at [this milestone](https://github.com/inbo/etn/milestone/2) for all issues that are included. + +* `tag_serial_number` is now the primary identifier for tags. Tags can have multiple types, subtypes and sensors. Acoustic information is related to the `acoustic_tag_id`. +* `acoustic` scope remains completely covered, but is now reflected in function names. This allows us to implement additional scopes (e.g. `cpod`) in the future. +* Deprecations for old function names. +* New tutorial on acoustic scope ([acoustic_telemetry.Rmd](https://github.com/inbo/etn/blob/main/vignettes/acoustic_telemetry.Rmd)). diff --git a/R/download_acoustic_dataset.R b/R/download_acoustic_dataset.R index 634b4d27..5fba38e6 100644 --- a/R/download_acoustic_dataset.R +++ b/R/download_acoustic_dataset.R @@ -60,7 +60,7 @@ #' #> * (4/6): downloading deployments.csv #' #> * (5/6): downloading receivers.csv #' #> * (6/6): adding datapackage.json as file metadata - +#' #> #' #> Summary statistics for dataset `2012_leopoldkanaal`: #' #> * number of animals: 104 #' #> * number of tags: 103 @@ -71,7 +71,7 @@ #' #> * last date of detection: 2021-09-02 #' #> * included scientific names: Anguilla anguilla #' #> * included acoustic projects: albert, Apelafico, bpns, JJ_Belwind, leopold, MOBEIA, pc4c, SPAWNSEIS, ws2, zeeschelde - +#' #> #' #> Warning message: #' #> In download_acoustic_dataset(animal_project_code = "2012_leopoldkanaal") : #' #> Found tags associated with multiple animals: 1145373 @@ -116,7 +116,7 @@ download_acoustic_dataset <- function(connection = con, animal_project_code = animal_project_code, scientific_name = scientific_name ) - readr::write_csv(animals, paste(directory, "animals.csv", sep = "/"), na = "") + readr::write_csv(animals, file.path(directory, "animals.csv"), na = "") # TAGS message("* (2/6): downloading tags.csv") @@ -135,7 +135,7 @@ download_acoustic_dataset <- function(connection = con, connection = connection, tag_serial_number = tag_serial_numbers ) - readr::write_csv(tags, paste(directory, "tags.csv", sep = "/"), na = "") + readr::write_csv(tags, file.path(directory, "tags.csv"), na = "") # DETECTIONS message("* (3/6): downloading detections.csv") @@ -151,7 +151,7 @@ download_acoustic_dataset <- function(connection = con, detections <- detections %>% distinct(.data$detection_id, .keep_all = TRUE) - readr::write_csv(detections, paste(directory, "detections.csv", sep = "/"), na = "") + readr::write_csv(detections, file.path(directory, "detections.csv"), na = "") # DEPLOYMENTS message("* (4/6): downloading deployments.csv") @@ -170,8 +170,14 @@ download_acoustic_dataset <- function(connection = con, # Remove linebreaks in deployment comments to get single lines in csv: deployments <- deployments %>% - dplyr::mutate(comments = stringr::str_replace_all(.data$comments, "[\r\n]+", " ")) - readr::write_csv(deployments, paste(directory, "deployments.csv", sep = "/"), na = "") + dplyr::mutate( + comments = stringr::str_replace_all(.data$comments, "[\r\n]+", " ") + ) + readr::write_csv( + deployments, + file.path(directory, "deployments.csv"), + na = "" + ) # RECEIVERS message("* (5/6): downloading receivers.csv") @@ -184,12 +190,16 @@ download_acoustic_dataset <- function(connection = con, connection = connection, receiver_id = receiver_ids ) - readr::write_csv(receivers, paste(directory, "receivers.csv", sep = "/"), na = "") + readr::write_csv(receivers, file.path(directory, "receivers.csv"), na = "") # DATAPACKAGE.JSON message("* (6/6): adding datapackage.json as file metadata") datapackage <- system.file("assets", "datapackage.json", package = "etn") - file.copy(datapackage, paste(directory, "datapackage.json", sep = "/"), overwrite = TRUE) + file.copy( + datapackage, + file.path(directory, "datapackage.json"), + overwrite = TRUE + ) # Create summary stats scientific_names <- @@ -199,21 +209,35 @@ download_acoustic_dataset <- function(connection = con, sort() message("") - message(glue::glue("\nSummary statistics for dataset `{animal_project_code}`:")) + message( + glue::glue("\nSummary statistics for dataset `{animal_project_code}`:") + ) message("* number of animals: ", nrow(animals)) message("* number of tags: ", nrow(tags)) message("* number of detections: ", nrow(detections)) message("* number of deployments: ", nrow(deployments)) message("* number of receivers: ", nrow(receivers)) if (nrow(detections) > 0) { - message("* first date of detection: ", detections %>% dplyr::summarize(min(as.Date(.data$date_time))) %>% pull()) - message("* last date of detection: ", detections %>% dplyr::summarize(max(as.Date(.data$date_time))) %>% pull()) + message( + "* first date of detection: ", + detections %>% dplyr::summarize(min(as.Date(.data$date_time))) %>% pull() + ) + message( + "* last date of detection: ", + detections %>% dplyr::summarize(max(as.Date(.data$date_time))) %>% pull() + ) } else { message("* first date of detection: ", NA) message("* last date of detection: ", NA) } - message("* included scientific names: ", paste(scientific_names, collapse = ", ")) - message("* included acoustic projects: ", paste(acoustic_project_codes, collapse = ", ")) + message( + "* included scientific names: ", + paste(scientific_names, collapse = ", ") + ) + message( + "* included acoustic projects: ", + paste(acoustic_project_codes, collapse = ", ") + ) message("") # Create warnings @@ -239,15 +263,28 @@ download_acoustic_dataset <- function(connection = con, duplicate_detections_count <- detections_orig_count - nrow(detections) if (length(animals_multiple_tags) > 0) { - warning("Found animals with multiple tags: ", paste(animals_multiple_tags, collapse = ", ")) + warning( + "Found animals with multiple tags: ", + paste(animals_multiple_tags, collapse = ", ") + ) } if (length(tags_multiple_animals) > 0) { - warning("Found tags associated with multiple animals: ", paste(tags_multiple_animals, collapse = ", ")) + warning( + "Found tags associated with multiple animals: ", + paste(tags_multiple_animals, collapse = ", ") + ) } if (length(orphaned_deployments) > 0) { - warning("Found deployments without acoustic project: ", paste(orphaned_deployments, collapse = ", ")) + warning( + "Found deployments without acoustic project: ", + paste(orphaned_deployments, collapse = ", ") + ) } if (duplicate_detections_count > 0) { - warning("Found and removed duplicate detections: ", duplicate_detections_count, " detections") + warning( + "Found and removed duplicate detections: ", + duplicate_detections_count, + " detections" + ) } } diff --git a/R/get_acoustic_detections.R b/R/get_acoustic_detections.R index 1157b096..50d32089 100644 --- a/R/get_acoustic_detections.R +++ b/R/get_acoustic_detections.R @@ -224,6 +224,7 @@ get_acoustic_detections <- function(connection = con, deployment_station_name AS station_name, -- exclusive to detections_limited deployment_latitude AS deploy_latitude, -- exclusive to detections_limited deployment_longitude AS deploy_longitude, -- exclusive to detections_limited + det.depth_in_meters AS depth_in_meters, det.sensor_value AS sensor_value, det.sensor_unit AS sensor_unit, det.sensor2_value AS sensor2_value, diff --git a/R/list_values.R b/R/list_values.R index 9b4b7285..3819a5e7 100644 --- a/R/list_values.R +++ b/R/list_values.R @@ -47,25 +47,35 @@ list_values <- function(.data, column, split = ",") { arguments <- as.list(match.call()) - if (is.numeric(arguments$column)){ + if (is.numeric(arguments$column)) { col_number <- arguments$column n_col_df <- ncol(.data) - assertthat::assert_that(as.integer(col_number) == col_number, - msg = "column number must be an integer") - assertthat::assert_that(col_number <= ncol(.data), - msg = glue::glue("column number exceeds the number of columns ", - "of .data ({n_col_df})")) + assertthat::assert_that( + as.integer(col_number) == col_number, + msg = "column number must be an integer" + ) + assertthat::assert_that( + col_number <= ncol(.data), + msg = glue::glue( + "column number exceeds the number of columns ", + "of .data ({n_col_df})" + ) + ) # extract values - values <- .data[,col_number] + values <- .data[, col_number] # extract column name col_name <- names(.data)[col_number] } else { - #check column name + # check column name col_name <- as.character(arguments$column) - assertthat::assert_that(length(col_name) == 1, - msg = "invalid column value") - assertthat::assert_that(col_name %in% names(.data), - msg = glue::glue("column {col_name} not found in .data")) + assertthat::assert_that( + length(col_name) == 1, + msg = "invalid column value" + ) + assertthat::assert_that( + col_name %in% names(.data), + msg = glue::glue("column {col_name} not found in .data") + ) # extract values if (class(arguments$column) == "name") { @@ -77,9 +87,10 @@ list_values <- function(.data, column, split = ",") { } } - if (is.character(values)) + if (is.character(values)) { # extract all values by splitting strings using split value values <- unlist(strsplit(x = values, split = split)) + } # remove duplicates, unique values only values <- unique(values) diff --git a/inst/CITATION b/inst/CITATION new file mode 100644 index 00000000..af7a387e --- /dev/null +++ b/inst/CITATION @@ -0,0 +1,11 @@ +authors <- eval(parse(text = meta$`Authors@R`)) +authors <- authors[which(unlist(lapply(authors, function(x) { "aut" %in% x$role })))] + +bibentry( + bibtype = "manual", + title = paste(meta$Package, meta$Title, sep = ": "), + author = authors, + year = format(Sys.Date(), "%Y"), + note = sprintf("R package version %s", meta$Version), + url = "https://inbo.github.io/etn/" +) diff --git a/inst/assets/datapackage.json b/inst/assets/datapackage.json index 7ec227f3..460ca15d 100644 --- a/inst/assets/datapackage.json +++ b/inst/assets/datapackage.json @@ -346,6 +346,26 @@ "name": "battery_estimated_end_date", "type": "datetime" }, + { + "name": "length", + "type": "number" + }, + { + "name": "diameter", + "type": "number" + }, + { + "name": "weight", + "type": "number" + }, + { + "name": "floating", + "type": "boolean" + }, + { + "name": "archive_memory", + "type": "string" + }, { "name": "sensor_slope", "type": "number" @@ -550,6 +570,10 @@ "name": "deploy_longitude", "type": "number" }, + { + "name": "depth_in_meters", + "type": "number" + }, { "name": "sensor_value", "type": "number" @@ -894,4 +918,4 @@ } } ] -} +} \ No newline at end of file diff --git a/man/download_acoustic_dataset.Rd b/man/download_acoustic_dataset.Rd index a0d43413..6b619307 100644 --- a/man/download_acoustic_dataset.Rd +++ b/man/download_acoustic_dataset.Rd @@ -76,6 +76,7 @@ download_acoustic_dataset(animal_project_code = "2012_leopoldkanaal") #> * (4/6): downloading deployments.csv #> * (5/6): downloading receivers.csv #> * (6/6): adding datapackage.json as file metadata +#> #> Summary statistics for dataset `2012_leopoldkanaal`: #> * number of animals: 104 #> * number of tags: 103 @@ -86,6 +87,7 @@ download_acoustic_dataset(animal_project_code = "2012_leopoldkanaal") #> * last date of detection: 2021-09-02 #> * included scientific names: Anguilla anguilla #> * included acoustic projects: albert, Apelafico, bpns, JJ_Belwind, leopold, MOBEIA, pc4c, SPAWNSEIS, ws2, zeeschelde +#> #> Warning message: #> In download_acoustic_dataset(animal_project_code = "2012_leopoldkanaal") : #> Found tags associated with multiple animals: 1145373 diff --git a/man/etn-package.Rd b/man/etn-package.Rd index b481748f..2c716b58 100644 --- a/man/etn-package.Rd +++ b/man/etn-package.Rd @@ -20,10 +20,11 @@ Useful links: } \author{ -\strong{Maintainer}: Peter Desmet \email{peter.desmet@inbo.be} (\href{https://orcid.org/0000-0002-8442-8025}{ORCID}) +\strong{Maintainer}: Pieter Huybrechts \email{pieter.huybrechts@inbo.be} (\href{https://orcid.org/0000-0002-6658-6062}{ORCID}) Authors: \itemize{ + \item Peter Desmet \email{peter.desmet@inbo.be} (\href{https://orcid.org/0000-0002-8442-8025}{ORCID}) \item Damiano Oldoni \email{damiano.oldoni@inbo.be} (\href{https://orcid.org/0000-0003-3445-7562}{ORCID}) \item Stijn Van Hoey \email{stijnvanhoey@gmail.com} (\href{https://orcid.org/0000-0001-6413-3185}{ORCID}) } diff --git a/tests/testthat/_snaps/download_acoustic_dataset.md b/tests/testthat/_snaps/download_acoustic_dataset.md new file mode 100644 index 00000000..78dc9586 --- /dev/null +++ b/tests/testthat/_snaps/download_acoustic_dataset.md @@ -0,0 +1,25 @@ +# download_acoustic_dataset() returns message and summary stats + + Code + cat(download_acoustic_dataset(con, animal_project_code = "2014_demer")) + Message + Downloading data to directory `2014_demer`: + * (1/6): downloading animals.csv + * (2/6): downloading tags.csv + * (3/6): downloading detections.csv + * (4/6): downloading deployments.csv + * (5/6): downloading receivers.csv + * (6/6): adding datapackage.json as file metadata + + Summary statistics for dataset `2014_demer`: + * number of animals: 16 + * number of tags: 16 + * number of detections: 236918 + * number of deployments: 1081 + * number of receivers: 244 + * first date of detection: 2014-04-18 + * last date of detection: 2018-09-15 + * included scientific names: Petromyzon marinus, Rutilus rutilus, Silurus glanis, Squalius cephalus + * included acoustic projects: V2LCHASES, albert, demer, dijle, zeeschelde + + diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R new file mode 100644 index 00000000..ddc152d9 --- /dev/null +++ b/tests/testthat/helper.R @@ -0,0 +1,28 @@ +# HELPER FUNCTIONS FOR TESTTHAT TESTS + +#' Get schema fields for a resource in a Frictionless Data Package. +#' +#' This function returns the `fields` attribute from a Table Schema of a +#' specific resource in a Frictionless Data Package. +#' These can be compared with the headers in the provided data. +#' +#' @param datapackage List describing a Data Package as returned by +#' [frictionless::read_package()]. +#' @param table_name Name of the Data Resource to retrieve the fields from. +#' +#' @return List containing the schema fields of the requested resource. +#' @family helper functions +#' @noRd +fetch_schema_fields <- function(datapackage = datapackage, table_name) { + datapackage[["resources"]][[ + match( + table_name, + sapply( + datapackage[["resources"]], + function(x) x[["name"]] + ) + ) + ]][[ + "schema" + ]][["fields"]] +} diff --git a/tests/testthat/test-download_acoustic_dataset.R b/tests/testthat/test-download_acoustic_dataset.R index 6be9389a..58b71fc0 100644 --- a/tests/testthat/test-download_acoustic_dataset.R +++ b/tests/testthat/test-download_acoustic_dataset.R @@ -1,8 +1,15 @@ con <- connect_to_etn() -test_that("download_acoustic_dataset() creates the expected messages and files", { - download_dir <- "./temp_download" - dir.create(download_dir, recursive = TRUE, showWarnings = FALSE) +# Create a data package +evaluate_download <- evaluate_promise({ + download_acoustic_dataset( + con, + animal_project_code = "2014_demer", + directory = tempdir() + ) +}) + +test_that("download_acoustic_dataset() creates the expected files", { files_to_create <- c( "animals.csv", "tags.csv", @@ -11,31 +18,151 @@ test_that("download_acoustic_dataset() creates the expected messages and files", "receivers.csv", "datapackage.json" ) - message <- readLines("./test-download_acoustic_dataset-message.txt") - # Process output message - message <- paste0(message, "\n") - - # Run function - evaluate_download <- evaluate_promise({ - download_acoustic_dataset( - con, - animal_project_code = "2014_demer", - directory = download_dir - ) - }) - # Function creates the expected files - expect_true(all(sort(list.files(download_dir)) == sort(files_to_create))) - - # Function returns the expected output message - expect_true(all(evaluate_download$messages == message)) + expect_true(all(files_to_create %in% list.files(tempdir()))) +}) +test_that("download_acoustic_dataset() does not warnings for valid dataset", { # Function returns no warnings (character of length 0) expect_true(length(evaluate_download$warnings) == 0) +}) + +test_that("download_acoustic_dataset() returns message and summary stats", { + # call download_acoustic_dataset() and capture the output, compare to a local + # file. Covers warnings and messages, but will fail on an error. + expect_snapshot(cat(download_acoustic_dataset( + con, + animal_project_code = "2014_demer" + ))) + # After running, remove the files we just created + withr::defer(unlink("2014_demer")) +}) + +test_that("download_acoustic_dataset() creates the expected files", { + files_to_create <- c( + "animals.csv", + "tags.csv", + "detections.csv", + "deployments.csv", + "receivers.csv", + "datapackage.json" + ) + + # Function creates the expected files + expect_true(all(files_to_create %in% list.files(tempdir()))) # Function returns no result expect_null(evaluate_download$result) +}) + +test_that("download_acoustic_dataset() creates a valid Frictionless Data Package", { + # This will fail when a field is added to a get_ function but not to datapackage.json + datapackage <- + suppressMessages(frictionless::read_package(file.path(tempdir(), "datapackage.json"))) + ## Check for errors when reading the resource + expect_no_warning(suppressMessages(frictionless::read_resource(datapackage, "animals"))) + expect_no_warning(suppressMessages(frictionless::read_resource(datapackage, "tags"))) + expect_no_warning(suppressMessages(frictionless::read_resource(datapackage, "detections"))) + expect_no_warning(suppressMessages(frictionless::read_resource(datapackage, "deployments"))) + expect_no_warning(suppressMessages(frictionless::read_resource(datapackage, "receivers"))) +}) + + +test_that("download_acoustic_dataset() returns CSV files with expected columns", { + datapackage <- + suppressMessages(frictionless::read_package(file.path(tempdir(), "datapackage.json"))) + # Check the number of schema fields in the datapackage against the number of + # columns in the csv files + expect_length( + fetch_schema_fields(datapackage, "animals"), + ncol(readr::read_csv( + file.path(tempdir(), "animals.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_length( + fetch_schema_fields(datapackage, "tags"), + ncol(readr::read_csv( + file.path(tempdir(), "tags.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_length( + fetch_schema_fields(datapackage, "detections"), + ncol(readr::read_csv( + file.path(tempdir(), "detections.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_length( + fetch_schema_fields(datapackage, "deployments"), + ncol(readr::read_csv( + file.path(tempdir(), "deployments.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_length( + fetch_schema_fields(datapackage, "receivers"), + ncol(readr::read_csv( + file.path(tempdir(), "receivers.csv"), + n_max = 0, show_col_types = FALSE + )) + ) +}) - # Remove generated files and directories after test - unlink(download_dir, recursive = TRUE) +test_that("download_acoustic_dataset() returns CSV files with columns in expected order", { + datapackage <- + suppressMessages(frictionless::read_package(file.path(tempdir(), "datapackage.json"))) + # Check if the schema fields in the data package are exactly the same + # (thus also in the same order) as the header of the csv files + expect_identical( + sapply( + fetch_schema_fields(datapackage, "animals"), + function(x) x[["name"]] + ), + names(readr::read_csv( + file.path(tempdir(), "animals.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_identical( + sapply( + fetch_schema_fields(datapackage, "tags"), + function(x) x[["name"]] + ), + names(readr::read_csv( + file.path(tempdir(), "tags.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_identical( + sapply( + fetch_schema_fields(datapackage, "detections"), + function(x) x[["name"]] + ), + names(readr::read_csv( + file.path(tempdir(), "detections.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_identical( + sapply( + fetch_schema_fields(datapackage, "deployments"), + function(x) x[["name"]] + ), + names(readr::read_csv( + file.path(tempdir(), "deployments.csv"), + n_max = 0, show_col_types = FALSE + )) + ) + expect_identical( + sapply( + fetch_schema_fields(datapackage, "receivers"), + function(x) x[["name"]] + ), + names(readr::read_csv( + file.path(tempdir(), "receivers.csv"), + n_max = 0, show_col_types = FALSE + )) + ) }) diff --git a/tests/testthat/test-etn-deprecated.R b/tests/testthat/test-etn-deprecated.R index 3dbc7c87..e90490cb 100644 --- a/tests/testthat/test-etn-deprecated.R +++ b/tests/testthat/test-etn-deprecated.R @@ -2,7 +2,7 @@ con <- connect_to_etn() test_that("get_deployments() redirects to correct function", { expect_warning(get_deployments(con), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_deployments(con, network_project_code = "demer"), get_acoustic_deployments(con, acoustic_project_code = "demer") )) @@ -10,7 +10,7 @@ test_that("get_deployments() redirects to correct function", { test_that("get_detections() redirects to correct function", { expect_warning(get_detections(con, limit = TRUE), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_detections( con, tag_id = "A69-1601-16130", @@ -28,37 +28,37 @@ test_that("get_detections() redirects to correct function", { test_that("get_projects() redirects to correct function", { expect_warning(get_projects(con), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_projects(con), get_animal_projects(con) )) - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_projects(con, project_type = "animal"), get_animal_projects(con) )) - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_projects(con, project_type = "network"), get_acoustic_projects(con) )) - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_projects(con, application_type = "cpod"), get_cpod_projects(con) )) }) test_that("get_receivers() redirects to correct function", { expect_warning(get_receivers(con), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( get_receivers(con), get_acoustic_receivers(con) )) }) test_that("list_network_project_codes() redirects to correct function", { expect_warning(list_network_project_codes(con), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( list_network_project_codes(con), list_acoustic_project_codes(con) )) }) test_that("list_tag_ids() redirects to correct function", { expect_warning(list_tag_ids(con), "is deprecated") - suppressWarnings(expect_equal( + suppressWarnings(expect_identical( list_tag_ids(con), list_acoustic_tag_ids(con) )) }) diff --git a/tests/testthat/test-get_acoustic_deployments.R b/tests/testthat/test-get_acoustic_deployments.R index 9d531541..72be7f5c 100644 --- a/tests/testthat/test-get_acoustic_deployments.R +++ b/tests/testthat/test-get_acoustic_deployments.R @@ -15,7 +15,7 @@ test_that("get_acoustic_deployments() returns a tibble", { test_that("get_acoustic_deployments() returns unique deployment_id", { df <- get_acoustic_deployments(con) - expect_equal(nrow(df), nrow(df %>% distinct(deployment_id))) + expect_identical(nrow(df), nrow(df %>% distinct(deployment_id))) }) test_that("get_acoustic_deployments() returns the expected columns", { @@ -60,7 +60,7 @@ test_that("get_acoustic_deployments() returns the expected columns", { "log_depth_sample_period", "comments" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_acoustic_deployments() allows selecting on deployment_id", { @@ -69,9 +69,9 @@ test_that("get_acoustic_deployments() allows selecting on deployment_id", { expect_error(get_acoustic_deployments(con, deployment_id = c("1437", "not_a_deployment_id"))) # Select single value - single_select <- 1437 # From demer + single_select <- 1437L # From demer single_select_df <- get_acoustic_deployments(con, deployment_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(deployment_id) %>% pull(), c(single_select) ) @@ -80,7 +80,7 @@ test_that("get_acoustic_deployments() allows selecting on deployment_id", { # Select multiple values multi_select <- c("1437", 1588) # Characters are allowed multi_select_df <- get_acoustic_deployments(con, deployment_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(deployment_id) %>% pull() %>% sort(), c(as.integer(multi_select)) # Output will be all integer ) @@ -95,7 +95,7 @@ test_that("get_acoustic_deployments() allows selecting on receiver_id", { # Select single value single_select <- "VR2W-124070" # From demer single_select_df <- get_acoustic_deployments(con, receiver_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(receiver_id) %>% pull(), c(single_select) ) @@ -104,7 +104,7 @@ test_that("get_acoustic_deployments() allows selecting on receiver_id", { # Select multiple values multi_select <- c("VR2W-124070", "VR2W-124078") multi_select_df <- get_acoustic_deployments(con, receiver_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(receiver_id) %>% pull() %>% sort(), c(multi_select) ) @@ -119,14 +119,14 @@ test_that("get_acoustic_deployments() allows selecting on acoustic_project_code" # Select single value single_select <- "demer" single_select_df <- get_acoustic_deployments(con, acoustic_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(acoustic_project_code) %>% pull(), c(single_select) ) expect_gt(nrow(single_select_df), 0) # Selection is case insensitive - expect_equal( + expect_identical( get_acoustic_deployments(con, acoustic_project_code = "demer"), get_acoustic_deployments(con, acoustic_project_code = "DEMER") ) @@ -134,7 +134,7 @@ test_that("get_acoustic_deployments() allows selecting on acoustic_project_code" # Select multiple values multi_select <- c("demer", "dijle") multi_select_df <- get_acoustic_deployments(con, acoustic_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(acoustic_project_code) %>% pull() %>% sort(), c(multi_select) ) @@ -149,7 +149,7 @@ test_that("get_acoustic_deployments() allows selecting on station_name", { # Select single value single_select <- "de-9" # From demer single_select_df <- get_acoustic_deployments(con, station_name = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(station_name) %>% pull(), c(single_select) ) @@ -158,7 +158,7 @@ test_that("get_acoustic_deployments() allows selecting on station_name", { # Select multiple values multi_select <- c("de-10", "de-9") # Note that sort() will put de-10 before de-9 multi_select_df <- get_acoustic_deployments(con, station_name = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(station_name) %>% pull() %>% sort(), c(multi_select) ) @@ -174,7 +174,7 @@ test_that("get_acoustic_deployments() allows selecting on open deployments only" # Default returns all default_df <- get_acoustic_deployments(con, acoustic_project_code = "ws1") - expect_equal(default_df, all_df) + expect_identical(default_df, all_df) # Open only returns deployments with no end date open_only_df <- get_acoustic_deployments(con, acoustic_project_code = "ws1", open_only = TRUE) @@ -196,5 +196,5 @@ test_that("get_acoustic_deployments() allows selecting on multiple parameters", test_that("get_acoustic_deployments() does not return cpod deployments", { # POD-3330 is a cpod receiver df <- get_acoustic_deployments(con, receiver_id = "POD-3330") - expect_equal(nrow(df), 0) + expect_identical(nrow(df), 0L) }) diff --git a/tests/testthat/test-get_acoustic_detections.R b/tests/testthat/test-get_acoustic_detections.R index b490f15e..177ed957 100644 --- a/tests/testthat/test-get_acoustic_detections.R +++ b/tests/testthat/test-get_acoustic_detections.R @@ -7,19 +7,19 @@ test_that("get_acoustic_detections() returns error for incorrect connection", { ) }) +# Store the first 100 rows of the acoustic detections data for use in tests +df <- get_acoustic_detections(con, limit = TRUE) + test_that("get_acoustic_detections() returns a tibble", { - df <- get_acoustic_detections(con, limit = TRUE) expect_s3_class(df, "data.frame") expect_s3_class(df, "tbl") }) test_that("get_acoustic_detections() returns unique detection_id", { - df <- get_acoustic_detections(con, limit = TRUE) - expect_equal(nrow(df), nrow(df %>% distinct(detection_id))) + expect_identical(nrow(df), length(unique(df$detection_id))) }) test_that("get_acoustic_detections() returns the expected columns", { - df <- get_acoustic_detections(con, limit = TRUE) expected_col_names <- c( "detection_id", "date_time", @@ -33,6 +33,7 @@ test_that("get_acoustic_detections() returns the expected columns", { "station_name", "deploy_latitude", "deploy_longitude", + "depth_in_meters", "sensor_value", "sensor_unit", "sensor2_value", @@ -42,7 +43,7 @@ test_that("get_acoustic_detections() returns the expected columns", { "qc_flag", "deployment_id" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_acoustic_detections() allows selecting on start_date and end_date", { @@ -69,7 +70,7 @@ test_that("get_acoustic_detections() allows selecting on start_date and end_date expect_gt(as.POSIXct("2015-04-25", tz = "UTC"), max(end_day_df$date_time)) # Between - between_year_df <- get_acoustic_detections(con, start_date= "2015", end_date = "2016", animal_project_code = "2014_demer") + between_year_df <- get_acoustic_detections(con, start_date = "2015", end_date = "2016", animal_project_code = "2014_demer") expect_lte(as.POSIXct("2015-01-01", tz = "UTC"), min(between_year_df$date_time)) expect_gt(as.POSIXct("2016-01-01", tz = "UTC"), max(between_year_df$date_time)) between_month_df <- get_acoustic_detections(con, start_date = "2015-04", end_date = "2015-05", animal_project_code = "2014_demer") @@ -88,7 +89,7 @@ test_that("get_acoustic_detections() allows selecting on acoustic_tag_id", { # Select single value single_select <- "A69-1601-16130" # From 2014_demer single_select_df <- get_acoustic_detections(con, acoustic_tag_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(acoustic_tag_id) %>% pull(), c(single_select) ) @@ -97,7 +98,7 @@ test_that("get_acoustic_detections() allows selecting on acoustic_tag_id", { # Select multiple values multi_select <- c("A69-1601-16129", "A69-1601-16130") multi_select_df <- get_acoustic_detections(con, acoustic_tag_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(acoustic_tag_id) %>% pull() %>% sort(), c(multi_select) ) @@ -110,24 +111,29 @@ test_that("get_acoustic_detections() allows selecting on animal_project_code", { expect_error(get_acoustic_detections(con, animal_project_code = c("2014_demer", "not_a_project"))) # Select single value - single_select <- "2014_demer" + single_select <- "2015_homarus" single_select_df <- get_acoustic_detections(con, animal_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(animal_project_code) %>% pull(), c(single_select) ) expect_gt(nrow(single_select_df), 0) # Selection is case insensitive - expect_equal( - get_acoustic_detections(con, animal_project_code = "2014_demer", limit = TRUE), - get_acoustic_detections(con, animal_project_code = "2014_DEMER", limit = TRUE) + expect_identical( + # a limited query doesn't always return the same results, the order isn't guaranteed + dplyr::arrange( + get_acoustic_detections(con, animal_project_code = "2015_HOMARUS", limit = FALSE), + detection_id), + dplyr::arrange( + get_acoustic_detections(con, animal_project_code = "2015_HOMARUS", limit = FALSE), + detection_id) ) # Select multiple values multi_select <- c("2014_demer", "2015_dijle") multi_select_df <- get_acoustic_detections(con, animal_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(animal_project_code) %>% pull() %>% sort(), c(multi_select) ) @@ -143,7 +149,7 @@ test_that("get_acoustic_detections() allows selecting on scientific_name", { # Select single value single_select <- "Rutilus rutilus" single_select_df <- get_acoustic_detections(con, scientific_name = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(scientific_name) %>% pull(), c(single_select) ) @@ -152,7 +158,7 @@ test_that("get_acoustic_detections() allows selecting on scientific_name", { # Select multiple values multi_select <- c("Rutilus rutilus", "Silurus glanis") multi_select_df <- get_acoustic_detections(con, scientific_name = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(scientific_name) %>% pull() %>% sort(), c(multi_select) ) @@ -167,22 +173,27 @@ test_that("get_acoustic_detections() allows selecting on acoustic_project_code", # Select single value single_select <- "demer" single_select_df <- get_acoustic_detections(con, acoustic_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(acoustic_project_code) %>% pull(), c(single_select) ) expect_gt(nrow(single_select_df), 0) # Selection is case insensitive - expect_equal( - get_acoustic_detections(con, acoustic_project_code = "demer", limit = TRUE), - get_acoustic_detections(con, acoustic_project_code = "DEMER", limit = TRUE) + expect_identical( + # a limit doesn't guarantee the same records get returned every time + dplyr::arrange( + get_acoustic_detections(con, acoustic_project_code = "demer", limit = FALSE), + detection_id), + dplyr::arrange( + get_acoustic_detections(con, acoustic_project_code = "DEMER", limit = FALSE), + detection_id) ) # Select multiple values multi_select <- c("demer", "dijle") multi_select_df <- get_acoustic_detections(con, acoustic_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(acoustic_project_code) %>% pull() %>% sort(), c(multi_select) ) @@ -197,7 +208,7 @@ test_that("get_acoustic_detections() allows selecting on receiver_id", { # Select single value single_select <- "VR2W-124070" # From demer single_select_df <- get_acoustic_detections(con, receiver_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(receiver_id) %>% pull(), c(single_select) ) @@ -206,7 +217,7 @@ test_that("get_acoustic_detections() allows selecting on receiver_id", { # Select multiple values multi_select <- c("VR2W-124070", "VR2W-124078") multi_select_df <- get_acoustic_detections(con, receiver_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(receiver_id) %>% pull() %>% sort(), c(multi_select) ) @@ -221,7 +232,7 @@ test_that("get_acoustic_detections() allows selecting on station_name", { # Select single value single_select <- "de-9" # From demer single_select_df <- get_acoustic_detections(con, station_name = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(station_name) %>% pull(), c(single_select) ) @@ -230,7 +241,7 @@ test_that("get_acoustic_detections() allows selecting on station_name", { # Select multiple values multi_select <- c("de-10", "de-9") # Note that sort() will put de-10 before de-9 multi_select_df <- get_acoustic_detections(con, station_name = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(station_name) %>% pull() %>% sort(), c(multi_select) ) @@ -242,10 +253,10 @@ test_that("get_acoustic_detections() allows to limit to 100 records", { expect_error(get_acoustic_detections(con, limit = "not_a_logical")) # Limit - expect_equal(nrow(get_acoustic_detections(con, limit = TRUE)), 100) - expect_equal( + expect_identical(nrow(get_acoustic_detections(con, limit = TRUE)), 100L) + expect_identical( nrow(get_acoustic_detections(con, acoustic_project_code = "demer", limit = TRUE)), - 100 + 100L ) }) @@ -271,7 +282,7 @@ test_that("get_acoustic_detections() returns acoustic and acoustic-archival tags # A sentinel acoustic-archival tag with pressure + temperature sensor acoustic_archival_df <- get_acoustic_detections(con, acoustic_tag_id = c("A69-9006-11100", "A69-9006-11099")) expect_gt(nrow(acoustic_archival_df), 0) - expect_equal( + expect_identical( acoustic_archival_df %>% distinct(tag_serial_number) %>% pull(), "1400185" ) @@ -315,11 +326,11 @@ test_that("get_acoustic_detections() does not return duplicate detections when t df_394 <- get_acoustic_detections(con, acoustic_tag_id = "A69-1601-29925", start_date = "2012-12-14") # Expect no duplicates - expect_equal(nrow(df_both), nrow(df_both %>% distinct(detection_id))) + expect_identical(nrow(df_both), nrow(df_both %>% distinct(detection_id))) # Return correct animal within range - expect_equal(df_393 %>% distinct(animal_id) %>% pull, 393) - expect_equal(df_394 %>% distinct(animal_id) %>% pull, 394) + expect_identical(df_393 %>% distinct(animal_id) %>% pull(), 393L) + expect_identical(df_394 %>% distinct(animal_id) %>% pull(), 394L) }) test_that("get_acoustic_detections() does not return detections out of date range when tag is associated with animal", { @@ -333,8 +344,8 @@ test_that("get_acoustic_detections() does not return detections out of date rang expect_gt(nrow(in_range_df), 0) # Expect no detections outside range - expect_equal(nrow(pre_range_df), 0) - expect_equal(nrow(post_range_df), 0) + expect_identical(nrow(pre_range_df), 0L) + expect_identical(nrow(post_range_df), 0L) }) test_that("get_acoustic_detections() can return detections not (yet) associated with an animal", { diff --git a/tests/testthat/test-get_acoustic_projects.R b/tests/testthat/test-get_acoustic_projects.R index 7f4bba91..57656452 100644 --- a/tests/testthat/test-get_acoustic_projects.R +++ b/tests/testthat/test-get_acoustic_projects.R @@ -15,7 +15,7 @@ test_that("get_acoustic_projects() returns a tibble", { test_that("get_acoustic_projects() returns unique project_id", { df <- get_acoustic_projects(con) - expect_equal(nrow(df), nrow(df %>% distinct(project_id))) + expect_identical(nrow(df), nrow(df %>% distinct(project_id))) }) test_that("get_acoustic_projects() returns the expected columns", { @@ -36,7 +36,7 @@ test_that("get_acoustic_projects() returns the expected columns", { "moratorium", "imis_dataset_id" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_acoustic_projects() allows selecting on acoustic_project_code", { @@ -47,14 +47,14 @@ test_that("get_acoustic_projects() allows selecting on acoustic_project_code", { # Select single value single_select <- "demer" single_select_df <- get_acoustic_projects(con, acoustic_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(project_code) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Selection is case insensitive - expect_equal( + expect_identical( get_acoustic_projects(con, acoustic_project_code = "demer"), get_acoustic_projects(con, acoustic_project_code = "DEMER") ) @@ -62,15 +62,15 @@ test_that("get_acoustic_projects() allows selecting on acoustic_project_code", { # Select multiple values multi_select <- c("demer", "dijle") multi_select_df <- get_acoustic_projects(con, acoustic_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(project_code) %>% pull() %>% sort(), c(multi_select) ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_acoustic_projects() returns projects of type 'acoustic'", { - expect_equal( + expect_identical( get_acoustic_projects(con) %>% distinct(project_type) %>% pull(), "acoustic" ) diff --git a/tests/testthat/test-get_acoustic_receivers.R b/tests/testthat/test-get_acoustic_receivers.R index a56ed6d6..7cc3eba3 100644 --- a/tests/testthat/test-get_acoustic_receivers.R +++ b/tests/testthat/test-get_acoustic_receivers.R @@ -46,7 +46,7 @@ test_that("get_acoustic_receivers() returns the expected columns", { "ar_tilt_code", "ar_tilt_after_deploy" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_acoustic_receivers() allows selecting on receiver_id", { @@ -57,7 +57,7 @@ test_that("get_acoustic_receivers() allows selecting on receiver_id", { # Select single value single_select <- "VR2W-124070" # From demer single_select_df <- get_acoustic_receivers(con, receiver_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(receiver_id) %>% pull(), c(single_select) ) @@ -66,7 +66,7 @@ test_that("get_acoustic_receivers() allows selecting on receiver_id", { # Select multiple values multi_select <- c("VR2W-124070", "VR2W-124078") multi_select_df <- get_acoustic_receivers(con, receiver_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(receiver_id) %>% pull() %>% sort(), c(multi_select) ) @@ -83,7 +83,7 @@ test_that("get_acoustic_receivers() allows selecting on status", { # Select single value single_select <- "broken" single_select_df <- get_acoustic_receivers(con, status = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(status) %>% pull(), c(single_select) ) @@ -92,7 +92,7 @@ test_that("get_acoustic_receivers() allows selecting on status", { # Select multiple values multi_select <- c("broken", "lost") multi_select_df <- get_acoustic_receivers(con, status = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(status) %>% pull() %>% sort(), c(multi_select) ) @@ -102,5 +102,5 @@ test_that("get_acoustic_receivers() allows selecting on status", { test_that("get_acoustic_receivers() does not return cpod receivers", { # POD-3330 is a cpod receiver df <- get_acoustic_receivers(con, receiver_id = "POD-3330") - expect_equal(nrow(df), 0) + expect_identical(nrow(df), 0L) }) diff --git a/tests/testthat/test-get_animal_projects.R b/tests/testthat/test-get_animal_projects.R index 4dec0449..2184b852 100644 --- a/tests/testthat/test-get_animal_projects.R +++ b/tests/testthat/test-get_animal_projects.R @@ -15,7 +15,7 @@ test_that("get_animal_projects() returns a tibble", { test_that("get_animal_projects() returns unique project_id", { df <- get_animal_projects(con) - expect_equal(nrow(df), nrow(df %>% distinct(project_id))) + expect_identical(nrow(df), nrow(df %>% distinct(project_id))) }) test_that("get_animal_projects() returns the expected columns", { @@ -36,7 +36,7 @@ test_that("get_animal_projects() returns the expected columns", { "moratorium", "imis_dataset_id" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_animal_projects() allows selecting on animal_project_code", { @@ -47,14 +47,14 @@ test_that("get_animal_projects() allows selecting on animal_project_code", { # Select single value single_select <- "2014_demer" single_select_df <- get_animal_projects(con, animal_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(project_code) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Selection is case insensitive - expect_equal( + expect_identical( get_animal_projects(con, animal_project_code = "2014_demer"), get_animal_projects(con, animal_project_code = "2014_DEMER") ) @@ -62,15 +62,15 @@ test_that("get_animal_projects() allows selecting on animal_project_code", { # Select multiple values multi_select <- c("2014_demer", "2015_dijle") multi_select_df <- get_animal_projects(con, animal_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(project_code) %>% pull() %>% sort(), c(multi_select) ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_animal_projects() returns projects of type 'animal'", { - expect_equal( + expect_identical( get_animal_projects(con) %>% distinct(project_type) %>% pull(), "animal" ) diff --git a/tests/testthat/test-get_animals.R b/tests/testthat/test-get_animals.R index 38159a3f..caee8a55 100644 --- a/tests/testthat/test-get_animals.R +++ b/tests/testthat/test-get_animals.R @@ -15,7 +15,7 @@ test_that("get_animals() returns a tibble", { test_that("get_animals() returns unique animal_id", { df <- get_animals(con) - expect_equal(nrow(df), nrow(df %>% distinct(animal_id))) + expect_identical(nrow(df), nrow(df %>% distinct(animal_id))) }) test_that("get_animals() returns the expected columns", { @@ -88,7 +88,7 @@ test_that("get_animals() returns the expected columns", { "holding_temperature", "comments" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_animals() allows selecting on animal_id", { @@ -98,22 +98,22 @@ test_that("get_animals() allows selecting on animal_id", { expect_error(get_animals(con, animal_id = 20.2)) # Not an integer # Select single value - single_select <- 305 + single_select <- 305L single_select_df <- get_animals(con, animal_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(animal_id) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Select multiple values multi_select <- c(304, "305") # Characters are allowed multi_select_df <- get_animals(con, animal_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(animal_id) %>% pull() %>% sort(), c(as.integer(multi_select)) # Output will be all integer ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_animals() allows selecting on animal_project_code", { @@ -124,14 +124,14 @@ test_that("get_animals() allows selecting on animal_project_code", { # Select single value single_select <- "2014_demer" single_select_df <- get_animals(con, animal_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(animal_project_code) %>% pull(), c(single_select) ) expect_gt(nrow(single_select_df), 0) # Selection is case insensitive - expect_equal( + expect_identical( get_animals(con, animal_project_code = "2014_demer"), get_animals(con, animal_project_code = "2014_DEMER") ) @@ -139,7 +139,7 @@ test_that("get_animals() allows selecting on animal_project_code", { # Select multiple values multi_select <- c("2014_demer", "2015_dijle") multi_select_df <- get_animals(con, animal_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(animal_project_code) %>% pull() %>% sort(), c(multi_select) ) @@ -154,21 +154,21 @@ test_that("get_animals() allows selecting on tag_serial_number", { # Select single value single_select <- "1187450" # From 2014_demer single_select_df <- get_animals(con, tag_serial_number = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(tag_serial_number) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Note that not all tag_serial_number return a single row, e.g. "1119796" # Select multiple values multi_select <- c(1187449, "1187450") # Integers are allowed multi_select_df <- get_animals(con, tag_serial_number = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(tag_serial_number) %>% pull() %>% sort(), c(as.character(multi_select)) # Output will be all character ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_animals() allows selecting on scientific_name", { @@ -180,7 +180,7 @@ test_that("get_animals() allows selecting on scientific_name", { # Select single value single_select <- "Rutilus rutilus" single_select_df <- get_animals(con, scientific_name = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(scientific_name) %>% pull(), c(single_select) ) @@ -189,7 +189,7 @@ test_that("get_animals() allows selecting on scientific_name", { # Select multiple values multi_select <- c("Rutilus rutilus", "Silurus glanis") multi_select_df <- get_animals(con, scientific_name = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(scientific_name) %>% pull() %>% sort(), c(multi_select) ) @@ -203,14 +203,14 @@ test_that("get_animals() allows selecting on multiple parameters", { scientific_name = "Rutilus rutilus" ) # There are 2 Rutilus rutilus records in 2014_demer - expect_equal(nrow(multiple_parameters_df), 2) + expect_identical(nrow(multiple_parameters_df), 2L) }) test_that("get_animals() collapses multiple associated tags to one row", { # Animal 5841 (project SPAWNSEIS) has 2 associated tags (1280688,1280688) animal_two_tags_df <- get_animals(con, animal_id = 5841) - expect_equal(nrow(animal_two_tags_df), 1) # Rows should be collapsed + expect_identical(nrow(animal_two_tags_df), 1L) # Rows should be collapsed # Columns starting with tag_ and acoustic_tag_id are collapsed with comma tag_col_names <- c( @@ -234,11 +234,11 @@ test_that("get_animals() returns correct tag_type and tag_subtype", { df <- get_animals(con) df <- df %>% filter(!stringr::str_detect(tag_type, ",")) # Remove multiple associated tags df <- df %>% filter(tag_type != "") # TODO: remove after https://github.com/inbo/etn/issues/249 - expect_equal( + expect_identical( df %>% distinct(tag_type) %>% pull() %>% sort(), c("acoustic", "acoustic-archival") # "archival" currently not in data ) - expect_equal( + expect_identical( df %>% distinct(tag_subtype) %>% pull() %>% sort(), c("animal", "built-in", "range", "sentinel") ) @@ -247,5 +247,5 @@ test_that("get_animals() returns correct tag_type and tag_subtype", { test_that("get_animals() does not return animals without tags", { # All animals should be related with a tag df <- get_animals(con) - expect_equal(df %>% filter(is.na(tag_serial_number)) %>% nrow(), 0) + expect_identical(df %>% filter(is.na(tag_serial_number)) %>% nrow(), 0L) }) diff --git a/tests/testthat/test-get_cpod_projects.R b/tests/testthat/test-get_cpod_projects.R index be42fc27..16f84300 100644 --- a/tests/testthat/test-get_cpod_projects.R +++ b/tests/testthat/test-get_cpod_projects.R @@ -15,7 +15,7 @@ test_that("get_cpod_projects() returns a tibble", { test_that("get_cpod_projects() returns unique project_id", { df <- get_cpod_projects(con) - expect_equal(nrow(df), nrow(df %>% distinct(project_id))) + expect_identical(nrow(df), nrow(df %>% distinct(project_id))) }) test_that("get_cpod_projects() returns the expected columns", { @@ -36,7 +36,7 @@ test_that("get_cpod_projects() returns the expected columns", { "moratorium", "imis_dataset_id" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_cpod_projects() allows selecting on cpod_project_code", { @@ -47,14 +47,14 @@ test_that("get_cpod_projects() allows selecting on cpod_project_code", { # Select single value single_select <- "cpod-lifewatch" single_select_df <- get_cpod_projects(con, cpod_project_code = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(project_code) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Selection is case insensitive - expect_equal( + expect_identical( get_cpod_projects(con, cpod_project_code = "cpod-lifewatch"), get_cpod_projects(con, cpod_project_code = "CPOD-LIFEWATCH") ) @@ -62,15 +62,15 @@ test_that("get_cpod_projects() allows selecting on cpod_project_code", { # Select multiple values multi_select <- c("cpod-lifewatch", "cpod-od-natuur") multi_select_df <- get_cpod_projects(con, cpod_project_code = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(project_code) %>% pull() %>% sort(), c(multi_select) ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_cpod_projects() returns projects of type 'cpod'", { - expect_equal( + expect_identical( get_cpod_projects(con) %>% distinct(project_type) %>% pull(), "cpod" ) diff --git a/tests/testthat/test-get_tags.R b/tests/testthat/test-get_tags.R index 570915aa..489b7a7a 100644 --- a/tests/testthat/test-get_tags.R +++ b/tests/testthat/test-get_tags.R @@ -71,7 +71,7 @@ test_that("get_tags() returns the expected columns", { "tag_id", "tag_device_id" ) - expect_equal(names(df), expected_col_names) + expect_identical(names(df), expected_col_names) }) test_that("get_tags() allows selecting on tag_serial_number", { @@ -82,21 +82,21 @@ test_that("get_tags() allows selecting on tag_serial_number", { # Select single value single_select <- "1187450" # From 2014_demer single_select_df <- get_tags(con, tag_serial_number = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(tag_serial_number) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Note that not all tag_serial_number return a single row, see further test # Select multiple values multi_select <- c(1187449, "1187450") # Integers are allowed multi_select_df <- get_tags(con, tag_serial_number = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(tag_serial_number) %>% pull() %>% sort(), c(as.character(multi_select)) # Output will be all character ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_tags() allows selecting on tag_type", { @@ -107,7 +107,7 @@ test_that("get_tags() allows selecting on tag_type", { # Select single value single_select <- "archival" single_select_df <- get_tags(con, tag_type = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(tag_type) %>% pull(), c(single_select) ) @@ -116,7 +116,7 @@ test_that("get_tags() allows selecting on tag_type", { # Select multiple values multi_select <- c("acoustic-archival", "archival") multi_select_df <- get_tags(con, tag_type = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(tag_type) %>% pull() %>% sort(), c(multi_select) ) @@ -131,7 +131,7 @@ test_that("get_tags() allows selecting on tag_subtype", { # Select single value single_select <- "built-in" single_select_df <- get_tags(con, tag_subtype = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(tag_subtype) %>% pull(), c(single_select) ) @@ -140,7 +140,7 @@ test_that("get_tags() allows selecting on tag_subtype", { # Select multiple values multi_select <- c("built-in", "range") multi_select_df <- get_tags(con, tag_subtype = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(tag_subtype) %>% pull() %>% sort(), c(multi_select) ) @@ -155,21 +155,21 @@ test_that("get_tags() allows selecting on acoustic_tag_id", { # Select single value single_select <- "A69-1601-16130" # From 2014_demer single_select_df <- get_tags(con, acoustic_tag_id = single_select) - expect_equal( + expect_identical( single_select_df %>% distinct(acoustic_tag_id) %>% pull(), c(single_select) ) - expect_equal(nrow(single_select_df), 1) + expect_identical(nrow(single_select_df), 1L) # Note that not all acoustic_tag_id return a single row, e.g. "A180-1702-48973" # Select multiple values multi_select <- c("A69-1601-16129", "A69-1601-16130") multi_select_df <- get_tags(con, acoustic_tag_id = multi_select) - expect_equal( + expect_identical( multi_select_df %>% distinct(acoustic_tag_id) %>% pull() %>% sort(), c(multi_select) ) - expect_equal(nrow(multi_select_df), 2) + expect_identical(nrow(multi_select_df), 2L) }) test_that("get_tags() allows selecting on multiple parameters", { @@ -180,14 +180,14 @@ test_that("get_tags() allows selecting on multiple parameters", { tag_subtype = "animal", acoustic_tag_id = "A69-1601-16130" ) - expect_equal(nrow(multiple_parameters_df), 1) + expect_identical(nrow(multiple_parameters_df), 1L) }) test_that("get_tags() can return multiple rows for a single tag", { # A sentinel acoustic-archival tag with temperature + pressure sensor tag_1_df <- get_tags(con, tag_serial_number = 1400185) - expect_equal(nrow(tag_1_df), 2) # 2 rows: temperature + presure - expect_equal( + expect_identical(nrow(tag_1_df), 2L) # 2 rows: temperature + presure + expect_identical( tag_1_df %>% dplyr::arrange(acoustic_tag_id) %>% distinct(tag_type, tag_subtype, sensor_type, acoustic_tag_id), @@ -202,8 +202,8 @@ test_that("get_tags() can return multiple rows for a single tag", { # A built-in acoustic tag with two protocols: https://github.com/inbo/etn/issues/177#issuecomment-925578186 tag_2_df <- get_tags(con, tag_serial_number = 461076) - expect_equal(nrow(tag_2_df), 2) # 2 rows: A180 + H170 - expect_equal( + expect_identical(nrow(tag_2_df), 2L) # 2 rows: A180 + H170 + expect_identical( tag_2_df %>% dplyr::arrange(acoustic_tag_id) %>% distinct(tag_type, tag_subtype, sensor_type, acoustic_tag_id), @@ -219,11 +219,11 @@ test_that("get_tags() can return multiple rows for a single tag", { test_that("get_tags() returns correct tag_type and tag_subtype", { df <- get_tags(con) - expect_equal( + expect_identical( df %>% distinct(tag_type) %>% pull() %>% sort(), c("acoustic", "acoustic-archival", "archival") ) - expect_equal( + expect_identical( df %>% distinct(tag_subtype) %>% pull() %>% sort(), c("animal", "built-in", "range", "sentinel") ) diff --git a/tests/testthat/test-list_acoustic_project_codes.R b/tests/testthat/test-list_acoustic_project_codes.R index 03ab45f9..21a64a61 100644 --- a/tests/testthat/test-list_acoustic_project_codes.R +++ b/tests/testthat/test-list_acoustic_project_codes.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_acoustic_project_codes() returns unique list of values", { vector <- list_acoustic_project_codes(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_acoustic_tag_ids.R b/tests/testthat/test-list_acoustic_tag_ids.R index 76a59e3a..501bde2b 100644 --- a/tests/testthat/test-list_acoustic_tag_ids.R +++ b/tests/testthat/test-list_acoustic_tag_ids.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_acoustic_tag_ids() returns unique list of values", { vector <- list_acoustic_tag_ids(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_animal_project_codes.R b/tests/testthat/test-list_animal_project_codes.R index ffe197c0..752fcb4a 100644 --- a/tests/testthat/test-list_animal_project_codes.R +++ b/tests/testthat/test-list_animal_project_codes.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_animal_project_codes() returns unique list of values", { vector <- list_animal_project_codes(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_cpod_project_codes.R b/tests/testthat/test-list_cpod_project_codes.R index e25d490e..54587699 100644 --- a/tests/testthat/test-list_cpod_project_codes.R +++ b/tests/testthat/test-list_cpod_project_codes.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_cpod_project_codes() returns unique list of values", { vector <- list_cpod_project_codes(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_deployment_ids.R b/tests/testthat/test-list_deployment_ids.R index ed16748e..21b697a1 100644 --- a/tests/testthat/test-list_deployment_ids.R +++ b/tests/testthat/test-list_deployment_ids.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_deployment_ids() returns unique list of values", { vector <- list_deployment_ids(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_receiver_ids.R b/tests/testthat/test-list_receiver_ids.R index ca6f766f..5db4e173 100644 --- a/tests/testthat/test-list_receiver_ids.R +++ b/tests/testthat/test-list_receiver_ids.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_receiver_ids() returns unique list of values", { vector <- list_receiver_ids(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_scientific_names.R b/tests/testthat/test-list_scientific_names.R index 18fd5a3c..34318f55 100644 --- a/tests/testthat/test-list_scientific_names.R +++ b/tests/testthat/test-list_scientific_names.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_scientific_names() returns unique list of values", { vector <- list_scientific_names(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_station_names.R b/tests/testthat/test-list_station_names.R index 2b87abf5..41ad45e3 100644 --- a/tests/testthat/test-list_station_names.R +++ b/tests/testthat/test-list_station_names.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_station_names() returns unique list of values", { vector <- list_station_names(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_tag_serial_numbers.R b/tests/testthat/test-list_tag_serial_numbers.R index acf95155..b41ac5e6 100644 --- a/tests/testthat/test-list_tag_serial_numbers.R +++ b/tests/testthat/test-list_tag_serial_numbers.R @@ -3,7 +3,7 @@ con <- connect_to_etn() test_that("list_tag_serial_numbers() returns unique list of values", { vector <- list_tag_serial_numbers(con) - expect_is(vector, "character") + expect_type(vector, "character") expect_false(any(duplicated(vector))) expect_true(all(!is.na(vector))) diff --git a/tests/testthat/test-list_values.R b/tests/testthat/test-list_values.R index 637dd2cd..dc1a3ca9 100644 --- a/tests/testthat/test-list_values.R +++ b/tests/testthat/test-list_values.R @@ -49,23 +49,53 @@ test_that("list_values() returns error for incorrect input", { test_that("list_values() returns a vector with unique values", { # Output has right class - expect_is(list_values(df, chr_col), class = "character") - expect_is(list_values(df, num_col), class = "numeric") + expect_type( + suppressMessages(list_values(df, chr_col)), type = "character" + ) + expect_type( + suppressMessages(list_values(df, num_col)), type = "double" + ) # Output value is correct with default split value (comma) - expect_equal(list_values(df, chr_col), c("A", "B", "C", "D")) + expect_identical( + suppressMessages(list_values(df, chr_col)), + c("A", "B", "C", "D") + ) # Output value is correct with non default split value - expect_equal(list_values(df, dot_sep_col, "\\."), c("A", "B", "C", "D")) + expect_identical( + suppressMessages(list_values(df, dot_sep_col, "\\.")), + c("A", "B", "C", "D") + ) # Output value doesn't depend on the way column is passed - expect_equal(list_values(df, column = chr_col), list_values(df, "chr_col")) - expect_equal(list_values(df, column = chr_col), list_values(df, 1)) - expect_equal(list_values(df, "num_col"), c(1, 2, 3)) + expect_identical( + suppressMessages(list_values(df, column = chr_col)), + suppressMessages(list_values(df, "chr_col")) + ) + expect_identical( + suppressMessages(list_values(df, column = chr_col)), + suppressMessages(list_values(df, 1)) + ) + expect_identical( + suppressMessages(list_values(df, "num_col")), + c(1, 2, 3) + ) # If the split value is not present in column, return a copy of the column - expect_equal( - list_values(df, "dot_sep_col", split = ","), + expect_identical( + suppressMessages(list_values(df, "dot_sep_col", split = ",")), df$dot_sep_col ) }) + +test_that("list_values() returns message on console", { + expect_message(list_values(df, "num_col"), + regexp = "3 unique num_col values", + fixed = TRUE + ) + expect_message(list_values(df, "chr_col", split = ","), + regexp = "4 unique chr_col values", + fixed = TRUE + ) +}) diff --git a/vignettes/acoustic_telemetry.Rmd b/vignettes/acoustic_telemetry.Rmd index b344e7e7..28c0bd94 100644 --- a/vignettes/acoustic_telemetry.Rmd +++ b/vignettes/acoustic_telemetry.Rmd @@ -194,7 +194,7 @@ detections_silurus %>% Sometimes it's interesting to know the number of detections per station: ```{r n_detections_per_deployment} -n_detect_station <- +n_detect_station <- detections_silurus %>% group_by(station_name) %>% count() @@ -204,7 +204,7 @@ n_detect_station It's also interesting to know the number of unique individuals per station: ```{r n_silurus_station} -n_silurus_station <- +n_silurus_station <- detections_silurus %>% distinct(station_name, animal_id) %>% group_by(station_name) %>% @@ -243,7 +243,7 @@ list_acoustic_tag_ids() %>% head(10) The detection of Wels catfishes has been possible thanks to one or more acoustic network projects, mentioned in field `acoustic_project_code`. You can retrieve them via the _list_ function `list_values()`: ```{r acoustic_project_codes_involved} -acoustic_project_codes <- detections_silurus %>% +acoustic_project_codes <- detections_silurus %>% list_values(acoustic_project_code) acoustic_project_codes ``` @@ -268,7 +268,7 @@ list_acoustic_project_codes() %>% head(10) You can retrieve deployment information related to the acoustic networks in `acoustic_project_codes` by using `get_acoustic_deployments()` function: ```{r get_acoustic_deployments_info_networks} -deployments <-get_acoustic_deployments( +deployments <- get_acoustic_deployments( acoustic_project_code = acoustic_project_codes ) deployments @@ -277,7 +277,7 @@ deployments These are the deployments of the acoustic receivers involved in `detections_silurus`: ```{r deploys_silurus} -deploys_silurus <- +deploys_silurus <- detections_silurus %>% list_values(deployment_id) deploys_silurus @@ -295,8 +295,8 @@ deployments_silurus Deployment duration: ```{r deployment_duration} -deployments_silurus_duration <- - deployments_silurus %>% +deployments_silurus_duration <- + deployments_silurus %>% mutate(duration = as.duration(recover_date_time - deploy_date_time)) %>% select(deployment_id, station_name, duration) %>% arrange(deployment_id) @@ -306,7 +306,7 @@ deployments_silurus_duration Number of days a deployment detected the passage of one or more individuals: ```{r n_active_days_deployments_silurus} -n_active_days_deployments_silurus <- +n_active_days_deployments_silurus <- detections_silurus %>% mutate(date = date(date_time)) %>% distinct(deployment_id, station_name, date) %>% @@ -319,13 +319,15 @@ n_active_days_deployments_silurus Relative detection duration, i.e. number of days with at least one detection divided by deployment duration: ```{r relative_detection_duration} -rel_det_duration_silurus <- +rel_det_duration_silurus <- n_active_days_deployments_silurus %>% left_join( deployments_silurus_duration, by = c("deployment_id", "station_name") ) %>% - mutate(relative_detection_duration = n_days*(24*60*60) / as.numeric(duration)) %>% + mutate( + relative_detection_duration = n_days * (24 * 60 * 60) / as.numeric(duration) + ) %>% select(deployment_id, station_name, relative_detection_duration) rel_det_duration_silurus ``` @@ -337,12 +339,12 @@ Aside standard graphs, the geographical component of telemetry data makes intera We can for example create a map of the involved stations showing the station name and the acoustic project code it belongs to as pop-ups. First, we retrieve the coordinates of the stations: ```{r geo_info_stations} -geo_info_stations <- +geo_info_stations <- detections_silurus %>% distinct( - station_name, - deploy_latitude, - deploy_longitude, + station_name, + deploy_latitude, + deploy_longitude, acoustic_project_code ) %>% arrange(station_name) @@ -389,7 +391,7 @@ n_detect_station %>% paste0("Station: ", station_name, " (", acoustic_project_code, ")"), paste0("# detections: ", n) ) - ) %>% + ) %>% addLegend( title = "Detections", pal = pal, @@ -425,7 +427,7 @@ n_silurus_station %>% paste0("Station: ", station_name, " (", acoustic_project_code, ")"), paste0("# detected individuals: ", n) ) - ) %>% + ) %>% addLegend( title = "Detected individuals", pal = pal, @@ -436,12 +438,12 @@ n_silurus_station %>% We can also make a map of the relative detection duration of the deployments. First, we have to retrieve the deployment geographical coordinates: ```{r geo_info_deployments} -geo_info_deploys <- +geo_info_deploys <- detections_silurus %>% distinct( - deployment_id, - deploy_latitude, - deploy_longitude, + deployment_id, + deploy_latitude, + deploy_longitude, station_name, acoustic_project_code ) %>% @@ -468,7 +470,7 @@ rel_det_duration_silurus %>% addCircleMarkers( lng = ~deploy_longitude, lat = ~deploy_latitude, - radius = ~100*relative_detection_duration, + radius = ~100 * relative_detection_duration, color = ~pal(relative_detection_duration), fillOpacity = 0.8, stroke = FALSE, @@ -479,7 +481,7 @@ rel_det_duration_silurus %>% paste0("Station: ", station_name, " (", acoustic_project_code, ")"), paste0("# relative detection duration: ", round(relative_detection_duration, 2)) ) - ) %>% + ) %>% addLegend( title = "Relative detection duration", pal = pal,