Skip to content

Commit

Permalink
Merge pull request #296 from inbo/improve-version-detection
Browse files Browse the repository at this point in the history
Improve version detection
  • Loading branch information
damianooldoni authored Jan 16, 2024
2 parents 4b2f513 + 7815038 commit 45b72a2
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 35 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: camtraptor
Title: Read, Explore and Visualize Camera Trap Data Packages
Version: 0.24.0
Version: 0.25.0
Authors@R: c(
person("Damiano", "Oldoni", email = "[email protected]",
role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3445-7562")),
Expand Down
26 changes: 22 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
# camtraptor 0.25.0

- `read_camtrap_dp()` detects Camtrap DP version from `package$profile` using
regex (#295).
This supports reading Camtrap DPs created by the GBIF IPT.

# camtraptor 0.24.0

- Replicate old Camtrap DP 0.1.6 behaviour and populate `angle` and `radius` for
event-based observations.
Values are taken from the first media-based observation (fields
`individualPositionRadius` and `individualPositionAngle`) for each
`eventID/individualID` combination (#291).

# camtraptor 0.23.0

- Fix bug in `read_camtrap_dp()` when reading a Camtrap DP 1.0 (#292).

# camtraptor 0.22.0

- Fix bug in `write_eml()` for Camtrap DP 1.0 datasets (#290).
Expand All @@ -6,10 +24,10 @@

# camtraptor 0.21.0

- `read_camtrap_dp()` supports Camtrap DP 1.0 (upcoming Agouti export format)
in favour of Camtrap DP 1.0-rc.1 (#284).
To avoid breaking changes to users, it will down-convert Camtrap DP 1.0 to
0.1.6 which is currently used as internal data model for camtraptor.
- `read_camtrap_dp()` supports Camtrap DP 1.0 (upcoming Agouti export format) in
favour of Camtrap DP 1.0-rc.1 (#284).
To avoid breaking changes to users, it will down-convert Camtrap DP 1.0 to 0.1.6
which is currently used as internal data model for camtraptor.
- `get_custom_effort()` now calculates per calendar month/week (#219).
- `write_dwc()` has an updated mapping for dwc_audubon.csv (#274).
- `get_record_table()` returns the number of observed individuals (#279).
Expand Down
44 changes: 16 additions & 28 deletions R/read_camtrap_dp.R
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
read_camtrap_dp <- function(file = NULL,
media = TRUE,
path = lifecycle::deprecated()) {
# check path (deprecated)
# Check path (deprecated)
warning_detail <- paste(
"Use argument `file` containing the path or URL to the `datapackage.json`",
"file. The use of parameter `path` with path to the local directory is ",
Expand All @@ -62,39 +62,26 @@ read_camtrap_dp <- function(file = NULL,
details = warning_detail
)
}
# define the right file value
# Define the right file value
if (lifecycle::is_present(path)) {
file <- file.path(path, "datapackage.json")
}
# file value is a valid path
# File value is a valid path
if (dir.exists(file)) {
file <- file.path(file, "datapackage.json")
}
# check media arg
# Check media arg
assertthat::assert_that(
media %in% c(TRUE, FALSE),
msg = "`media` must be a logical: TRUE or FALSE"
)

# read package (metadata)
# Read package (metadata)
package <- frictionless::read_package(file)

# supported versions
# Check Camtrap DP version is supported
version <- get_version(profile = package$profile)
supported_versions <- c("0.1.6", "1.0")

# get package version
profile <- package$profile
if (profile == "https://raw.githubusercontent.com/tdwg/camtrap-dp/1.0/camtrap-dp-profile.json") {
version <- "1.0"
} else {
if (profile == "https://raw.githubusercontent.com/tdwg/camtrap-dp/0.1.6/camtrap-dp-profile.json") {
version <- "0.1.6"
} else {
version <- profile
}
}

# check version is supported
assertthat::assert_that(
version %in% supported_versions,
msg = glue::glue(
Expand All @@ -103,9 +90,10 @@ read_camtrap_dp <- function(file = NULL,
)
)

# get resource names
# Get resource names
resource_names <- frictionless::resources(package)
#check needed resources are present

# Check needed resources are present
resources_to_read <- c("deployments", "media", "observations")
assertthat::assert_that(
all(resources_to_read %in% resource_names),
Expand All @@ -116,18 +104,18 @@ read_camtrap_dp <- function(file = NULL,
)
)

# read deployments
# Read deployments
deployments <- frictionless::read_resource(package, "deployments")
issues_deployments <- check_reading_issues(deployments, "deployments")
# read observations (needed to create sequenceID in media)
# Read observations (needed to create sequenceID in media)
observations <- frictionless::read_resource(package, "observations")
issues_observations <- check_reading_issues(observations, "observations")

if (version == "0.1.6"){
observations <- add_speed_radius_angle(observations)
}

# create first version datapackage with resources in data slot
# Create first version datapackage with resources in data slot
data <- list(
"deployments" = deployments,
"media" = NULL,
Expand All @@ -136,7 +124,7 @@ read_camtrap_dp <- function(file = NULL,

package$data <- data

# read media if needed
# Read media if needed
if (media) {
media_df <- frictionless::read_resource(package, "media")
issues_media <- check_reading_issues(media_df, "media")
Expand All @@ -148,12 +136,12 @@ read_camtrap_dp <- function(file = NULL,

package <- add_taxonomic_info(package)

# convert to 0.1.6
# Convert to 0.1.6
if (version == "1.0") {
package <- convert_to_0.1.6(package, version, media = media)
}

# order columns
# Order columns
package$data$deployments <- order_cols_deployments(package$data$deployments)
package$data$observations <- order_cols_observations(
package$data$observations
Expand Down
30 changes: 29 additions & 1 deletion R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,33 @@ check_value <- function(arg, options = NULL, arg_name, null_allowed = TRUE) {
}
}

#' Get version from data package profile
#'
#' This helper functions returns the version of a Camera Trap Data Package by
#' applying a regex to its `profile`.
#'
#' The regex rule extracts the version by detecting a sequence of digits and dots.
#' If no dots are detected or `"camtrap-dp-profile.json"` is not part of
#' `profile`, the entire `profile` is returned.
#'
#' @param profile Character containing the profile of the data package.
#' @return Character containing the data package version.
#' @noRd
get_version <- function(profile) {
pattern_regex <- "\\d+(\\.\\d+){1,2}" # a sequence of digits and dots (max 2)
extracted_version <- stringr::str_extract(
string = profile,
pattern = pattern_regex
)
if (stringr::str_detect(string = profile,
pattern = stringr::fixed("camtrap-dp-profile.json")) &
!is.na(extracted_version)) {
extracted_version
} else {
profile
}
}

#' Check reading issues
#'
#' This helper function throws a warning if issues while reading datapackage
Expand All @@ -78,8 +105,9 @@ check_value <- function(arg, options = NULL, arg_name, null_allowed = TRUE) {
#'
#' @param df Data.frame.
#' @param df_name Character with name of the data.frame passed to `df`.
#' @noRd
#' @return Data.frame containing the issues as returned by `readr::problems()`.
#' @noRd
#'
check_reading_issues <- function(df, df_name) {
# get problems
issues_df <- readr::problems(df)
Expand Down
2 changes: 1 addition & 1 deletion tests/testthat/test-read_camtrap_dp.R
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test_that("file can be an URL", {
test_that("only DP versions 1.0 and dp 0.1.6 are supported", {
expect_error(
suppressMessages(read_camtrap_dp("https://raw.githubusercontent.com/tdwg/camtrap-dp/bb046c85a55bef2ced709357c0047f0136df8326/example/datapackage.json")),
"Version `https://raw.githubusercontent.com/tdwg/camtrap-dp/0.5/camtrap-dp-profile.json` is not supported. Supported versions: 0.1.6 and 1.0",
"Version `0.5` is not supported. Supported versions: 0.1.6 and 1.0",
fixed = TRUE
)

Expand Down

0 comments on commit 45b72a2

Please sign in to comment.