Title: | Read and Manipulate Camera Trap Data Packages |
---|---|
Description: | Read and manipulate Camera Trap Data Packages ('Camtrap DP'). 'Camtrap DP' (<https://camtrap-dp.tdwg.org>) is a data exchange format for camera trap data. With 'camtrapdp' you can read, filter and transform data (including to Darwin Core) before further analysis in e.g. 'camtraptor' or 'camtrapR'. |
Authors: | Peter Desmet [aut, cre] (<https://orcid.org/0000-0002-8442-8025>, Research Institute for Nature and Forest (INBO)), Sanne Govaert [aut] (<https://orcid.org/0000-0002-8939-1305>, Research Institute for Nature and Forest (INBO)), Pieter Huybrechts [aut] (<https://orcid.org/0000-0002-6658-6062>, Research Institute for Nature and Forest (INBO)), Damiano Oldoni [aut] (<https://orcid.org/0000-0003-3445-7562>, Research Institute for Nature and Forest (INBO)), Research Institute for Nature and Forest (INBO) [cph] (https://www.vlaanderen.be/inbo/en-gb/), Research Foundation - Flanders [fnd] (https://lifewatch.be) |
Maintainer: | Peter Desmet <[email protected]> |
License: | MIT + file LICENSE |
Version: | 0.3.1.9000 |
Built: | 2024-10-25 12:29:13 UTC |
Source: | https://github.com/inbo/camtrapdp |
Checks if an object is a Camera Trap Data Package object with the required properties.
check_camtrapdp(x)
check_camtrapdp(x)
x |
Camera Trap Data Package object, as returned by |
x
invisibly or an error.
x <- example_dataset() check_camtrapdp(x) # Invisible return of x if valid
x <- example_dataset() check_camtrapdp(x) # Invisible return of x if valid
deployments()
gets the deployments from a Camera Trap Data Package object.
deployments<-()
is the assignment equivalent.
It should only be used within other functions, where the expected data structure can be guaranteed.
Metadata (x$spatial
and x$temporal
) are updated to match the assigned
deployments.
deployments(x) deployments(x) <- value
deployments(x) deployments(x) <- value
x |
Camera Trap Data Package object, as returned by |
value |
A data frame to assign as deployments. |
A tibble::tibble()
data frame with deployments.
Other accessor functions:
events()
,
locations()
,
media()
,
observations()
,
taxa()
x <- example_dataset() # Get deployments deployments(x) # Set deployments (not recommended outside a function) deployments(x) <- head(deployments(x), 1)
x <- example_dataset() # Get deployments deployments(x) # Set deployments (not recommended outside a function) deployments(x) <- head(deployments(x), 1)
Gets the (unique) events from the observations of a Camera Trap Data
Package object.
Only observations with observationLevel == "event"
are considered.
events(x)
events(x)
x |
Camera Trap Data Package object, as returned by |
A tibble::tibble()
data frame with the events, containing the
following columns:
deploymentID
eventID
eventStart
eventEnd
Other accessor functions:
deployments()
,
locations()
,
media()
,
observations()
,
taxa()
x <- example_dataset() events(x)
x <- example_dataset() events(x)
Reads the Camtrap DP example dataset. This dataset is maintained and versioned with the Camtrap DP standard.
example_dataset()
example_dataset()
Camera Trap Data Package object.
example_dataset()
example_dataset()
Subsets deployments in a Camera Trap Data Package object, retaining all rows that satisfy the conditions.
Media are filtered on associated deploymentID
.
Observations are filtered on associated deploymentID
.
Metadata (x$spatial
, x$temporal
and x$taxonomic
) are updated to match
the filtered deployments.
filter_deployments(x, ...)
filter_deployments(x, ...)
x |
Camera Trap Data Package object, as returned by |
... |
Filtering conditions, see |
x
filtered.
Other filter functions:
filter_media()
,
filter_observations()
x <- example_dataset() # Filtering returns x, so pipe with deployments() to see the result x %>% filter_deployments(deploymentID == "62c200a9") %>% deployments() # Filtering on deployments also affects associated media and observations x_filtered <- filter_deployments(x, deploymentID == "62c200a9") media(x_filtered) observations(x_filtered) # Filtering on multiple conditions (combined with &) x %>% filter_deployments(latitude > 51.0, longitude > 5.0) %>% deployments() # Filtering on dates is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_deployments( deploymentStart >= lubridate::as_date("2020-06-19"), deploymentEnd <= lubridate::as_date("2020-08-30") ) %>% deployments()
x <- example_dataset() # Filtering returns x, so pipe with deployments() to see the result x %>% filter_deployments(deploymentID == "62c200a9") %>% deployments() # Filtering on deployments also affects associated media and observations x_filtered <- filter_deployments(x, deploymentID == "62c200a9") media(x_filtered) observations(x_filtered) # Filtering on multiple conditions (combined with &) x %>% filter_deployments(latitude > 51.0, longitude > 5.0) %>% deployments() # Filtering on dates is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_deployments( deploymentStart >= lubridate::as_date("2020-06-19"), deploymentEnd <= lubridate::as_date("2020-08-30") ) %>% deployments()
Subsets media in a Camera Trap Data Package object, retaining all rows that satisfy the conditions.
Deployments are not filtered.
Observations are filtered on associated mediaID
(for media-based
observations) and eventID
(for event-based observations).
Metadata (x$taxonomic
) are updated to match the filtered observations.
filter_media(x, ...)
filter_media(x, ...)
x |
Camera Trap Data Package object, as returned by |
... |
Filtering conditions, see |
x
filtered.
Other filter functions:
filter_deployments()
,
filter_observations()
x <- example_dataset() # Filtering returns x, so pipe with media() to see the result x %>% filter_media(captureMethod == "timeLapse") %>% media() # Filtering on media also affects associated observations, but not deployments x_filtered <- filter_media(x, favorite == TRUE) observations(x_filtered) # Filtering on multiple conditions (combined with &) x %>% filter_media(captureMethod == "activityDetection", filePublic == FALSE) %>% media() # Filtering on datetimes is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_media( timestamp >= lubridate::as_datetime("2020-08-02 05:01:00"), timestamp <= lubridate::as_datetime("2020-08-02 05:02:00") ) %>% media()
x <- example_dataset() # Filtering returns x, so pipe with media() to see the result x %>% filter_media(captureMethod == "timeLapse") %>% media() # Filtering on media also affects associated observations, but not deployments x_filtered <- filter_media(x, favorite == TRUE) observations(x_filtered) # Filtering on multiple conditions (combined with &) x %>% filter_media(captureMethod == "activityDetection", filePublic == FALSE) %>% media() # Filtering on datetimes is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_media( timestamp >= lubridate::as_datetime("2020-08-02 05:01:00"), timestamp <= lubridate::as_datetime("2020-08-02 05:02:00") ) %>% media()
Subsets observations in a Camera Trap Data Package object, retaining all rows that satisfy the conditions.
Deployments are not filtered.
Media are filtered on associated mediaID
(for media-based observations)
and eventID
(for event-based observations).
Filter on observationLevel == "media"
to only retain directly linked media.
Metadata (x$taxonomic
) are updated to match the filtered observations.
filter_observations(x, ...)
filter_observations(x, ...)
x |
Camera Trap Data Package object, as returned by |
... |
Filtering conditions, see |
x
filtered.
Other filter functions:
filter_deployments()
,
filter_media()
x <- example_dataset() # Filtering returns x, so pipe with observations() to see the result x %>% filter_observations(observationType == "animal") %>% observations() # Filtering on observations also affects associated media, but not deployments x %>% filter_observations( scientificName == "Vulpes vulpes", observationLevel == "event" ) %>% media() x %>% filter_observations( scientificName == "Vulpes vulpes", observationLevel == "media" ) %>% media() # Filtering on multiple conditions (combined with &) x %>% filter_observations( deploymentID == "577b543a", scientificName %in% c("Martes foina", "Mustela putorius") ) %>% observations() # Filtering on datetimes is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_observations( eventStart >= lubridate::as_datetime("2020-06-19 22:00:00"), eventEnd <= lubridate::as_datetime("2020-06-19 22:10:00") ) %>% observations()
x <- example_dataset() # Filtering returns x, so pipe with observations() to see the result x %>% filter_observations(observationType == "animal") %>% observations() # Filtering on observations also affects associated media, but not deployments x %>% filter_observations( scientificName == "Vulpes vulpes", observationLevel == "event" ) %>% media() x %>% filter_observations( scientificName == "Vulpes vulpes", observationLevel == "media" ) %>% media() # Filtering on multiple conditions (combined with &) x %>% filter_observations( deploymentID == "577b543a", scientificName %in% c("Martes foina", "Mustela putorius") ) %>% observations() # Filtering on datetimes is easiest with lubridate library(lubridate, warn.conflicts = FALSE) x %>% filter_observations( eventStart >= lubridate::as_datetime("2020-06-19 22:00:00"), eventEnd <= lubridate::as_datetime("2020-06-19 22:10:00") ) %>% observations()
Gets the (unique) locations from the deployments of a Camera Trap Data Package object.
locations(x)
locations(x)
x |
Camera Trap Data Package object, as returned by |
A tibble::tibble()
data frame with the locations, containing the
following columns:
locationID
locationName
latitude
longitude
coordinateUncertainty
Other accessor functions:
deployments()
,
events()
,
media()
,
observations()
,
taxa()
x <- example_dataset() locations(x)
x <- example_dataset() locations(x)
media()
gets the media from a Camera Trap Data Package object.
media<-()
is the assignment equivalent.
It should only be used within other functions, where the expected data structure can be guaranteed.
media(x) media(x) <- value
media(x) media(x) <- value
x |
Camera Trap Data Package object, as returned by |
value |
A data frame to assign as media. |
A tibble::tibble()
data frame with media.
Other accessor functions:
deployments()
,
events()
,
locations()
,
observations()
,
taxa()
x <- example_dataset() # Get media media(x) # Set media (not recommended outside a function) media(x) <- head(media(x), 1)
x <- example_dataset() # Get media media(x) # Set media (not recommended outside a function) media(x) <- head(media(x), 1)
observations()
gets the observations from a Camera Trap Data Package
object.
observations<-()
is the assignment equivalent.
It should only be used within other functions, where the expected data structure can be guaranteed.
Metadata (x$taxonomic
) are updated to match the assigned observations.
observations(x) observations(x) <- value
observations(x) observations(x) <- value
x |
Camera Trap Data Package object, as returned by |
value |
A data frame to assign as observations. |
A tibble::tibble()
data frame with observations.
Other accessor functions:
deployments()
,
events()
,
locations()
,
media()
,
taxa()
x <- example_dataset() # Get the observations observations(x) # Set observations (not recommended outside a function) observations(x) <- head(observations(x), 1)
x <- example_dataset() # Get the observations observations(x) # Set observations (not recommended outside a function) observations(x) <- head(observations(x), 1)
Prints a human-readable summary of a Camera Trap Data Package, as an
extension of frictionless::print.datapackage()
.
## S3 method for class 'camtrapdp' print(x, ...)
## S3 method for class 'camtrapdp' print(x, ...)
x |
Camera Trap Data Package object, as returned by |
... |
Further arguments, they are ignored by this function. |
print()
with a summary of the Camera Trap Data Package object.
x <- example_dataset() # Print a summary print(x) # Print a summary after filtering filter_deployments(x, deploymentID == "62c200a9")
x <- example_dataset() # Print a summary print(x) # Print a summary after filtering filter_deployments(x, deploymentID == "62c200a9")
Reads files from a Camera Trap Data Package (Camtrap DP) into memory.
read_camtrapdp(file)
read_camtrapdp(file)
file |
Path or URL to a |
A Camera Trap Data Package object.
Camtrap DP metadata has a taxonomic
property that can contain extra
information for each scientificName
found in observations.
Such information can include higher taxonomy (family
, order
, etc.) and
vernacular names in multiple languages.
This function will automatically include this taxonomic information in
observations, as extra columns starting with taxon.
.
Observations can contain two classifications at two levels:
Media-based observations (observationLevel = "media"
) are based on a
single media file and are directly linked to it via mediaID
.
Event-based observations (observationLevel = "event"
) are based on an
event, defined as a combination of eventID
, eventStart
and eventEnd
.
This event can consist of one or more media files, but is not directly linked
to these.
This function will automatically assign eventID
s to media, using
media.deploymentID = event.deploymentID
and eventStart <= media.timestamp <= eventEnd
.
Note that this can result in media being linked to multiple events (and thus
being duplicated), for example when events and sub-events were defined.
Camtrap DP metadata has a spatial
and temporal
property that contains the
spatial and temporal coverage of the package respectively.
This function will automatically update the spatial and temporal scopes in metadata based on the data.
file <- "https://raw.githubusercontent.com/tdwg/camtrap-dp/1.0/example/datapackage.json" x <- read_camtrapdp(file) x
file <- "https://raw.githubusercontent.com/tdwg/camtrap-dp/1.0/example/datapackage.json" x <- read_camtrapdp(file) x
Rounds deployment coordinates to a certain number of digits to fuzzy/generalize camera trap locations. This function can be used before publishing data in order to protect sensitive species and/or prevent theft of active cameras.
round_coordinates(x, digits)
round_coordinates(x, digits)
x |
Camera Trap Data Package object, as returned by |
digits |
Number of decimal places to round coordinates to ( |
x
with chosen coordinatePrecision
in metadata and rounded
coordinates and calculated coordinateUncertainty
in deployments.
Rounding coordinates is a recommended method to generalize sensitive biodiversity information (see Section 4.2 in Chapman 2020). Use this function to do so for your data. Determine the category of sensitivity (see Section 2.2 in Chapman 2020) and choose the associated number of digits :
category | sensitivity | digits |
category 1 | extreme | (do not publish) |
category 2 | high | 1 |
category 3 | medium | 2 |
category 4 | low | 3 |
not sensitive | not sensitive | all (do not use this function) |
The function will:
Set the coordinatePrecision
in the metadata (original values will be
overwritten):
digits | coordinatePrecision |
1 | 0.1 |
2 | 0.01 |
3 | 0.001 |
Round all coordinates in the deployments to the selected number of digits.
Update the coordinateUncertainy
(in meters) in the deployments.
This uncertainty is based on the number of digits and the latitude,
following Table 3 in Chapman &
Wieczorek 2020:
digits | 0° latitude | 30° latitude | 60° latitude | 85° latitude |
1 | 15691 m | 14697 m | 12461 m | 11211 m |
2 | 1570 m | 1470 m | 1246 m | 1121 m |
3 | 157 m | 147 m | 125 m | 112 m |
If a coordinatePrecision
is already present, the function will subtract
the coordinateUncertainty
associated with it before setting a new
uncertainty (e.g. 0.001
to 0.01
= original value - 157 + 1570 m
).
If original value
is NA
, the function will assume the coordinates
were obtained by GPS and set original value = 30
.
Other transformation functions:
shift_time()
,
write_dwc()
,
write_eml()
x <- example_dataset() # Original precision x$coordinatePrecision # Original coordinates and uncertainty deployments(x)[c("latitude", "longitude", "coordinateUncertainty")] # Round coordinates to 1 digit x_rounded <- round_coordinates(x, 1) # Updated coordinatePrecision x_rounded$coordinatePrecision # Updated coordinates and uncertainty (original 187 - 147 + 14697 = 14737) deployments(x_rounded)[c("latitude", "longitude", "coordinateUncertainty")]
x <- example_dataset() # Original precision x$coordinatePrecision # Original coordinates and uncertainty deployments(x)[c("latitude", "longitude", "coordinateUncertainty")] # Round coordinates to 1 digit x_rounded <- round_coordinates(x, 1) # Updated coordinatePrecision x_rounded$coordinatePrecision # Updated coordinates and uncertainty (original 187 - 147 + 14697 = 14737) deployments(x_rounded)[c("latitude", "longitude", "coordinateUncertainty")]
Shifts date-times for selected deployments (and associated media and observations) by a specified duration. This function can be used to correct date-time issues such as incorrectly set time zones.
Deployments: deploymentStart
and deploymentEnd
are updated and
timestampIssues
is set to FALSE
.
Media: timestamp
is updated.
Observations: eventStart
and eventEnd
are updated.
Metadata (x$temporal
) are updated to match the new temporal scope.
shift_time(x, deployment_id, duration)
shift_time(x, deployment_id, duration)
x |
Camera Trap Data Package object, as returned by |
deployment_id |
One or more deploymentIDs. |
duration |
Difference between the current and new date-times.
Provide as a |
x
with shifted date-times.
Other transformation functions:
round_coordinates()
,
write_dwc()
,
write_eml()
# Set desired duration between current and new date-times (e.g. 4 hours earlier) library(lubridate, warn.conflicts = FALSE) duration(-4, units = "hours") # Or calculate one based on two date-times current <- ymd_hms("2024-04-01T04:00:00", tz = "UTC") new <- ymd_hms("2024-04-01T00:00:00", tz = "UTC") duration <- as.duration(interval(current, new)) # Shift date-times for 2 deployments x <- example_dataset() x_shifted <- shift_time(x, c("00a2c20d", "29b7d356"), duration) # Inspect results deployments(x)[, c("deploymentID", "deploymentStart", "deploymentEnd")] deployments(x_shifted)[, c("deploymentID", "deploymentStart", "deploymentEnd")]
# Set desired duration between current and new date-times (e.g. 4 hours earlier) library(lubridate, warn.conflicts = FALSE) duration(-4, units = "hours") # Or calculate one based on two date-times current <- ymd_hms("2024-04-01T04:00:00", tz = "UTC") new <- ymd_hms("2024-04-01T00:00:00", tz = "UTC") duration <- as.duration(interval(current, new)) # Shift date-times for 2 deployments x <- example_dataset() x_shifted <- shift_time(x, c("00a2c20d", "29b7d356"), duration) # Inspect results deployments(x)[, c("deploymentID", "deploymentStart", "deploymentEnd")] deployments(x_shifted)[, c("deploymentID", "deploymentStart", "deploymentEnd")]
Gets the (unique) scientific names and associated taxonomic information from
the observations of a Camera Trap Data Package object.
Duplicate taxa (i.e. with the same scientificName
) are removed, retaining
the taxon with (first) a taxonID
and (second) the most taxonomic
information.
taxa(x)
taxa(x)
x |
Camera Trap Data Package object, as returned by |
A tibble::tibble()
data frame with the taxonomic information,
containing at least a scientificName
column.
Other accessor functions:
deployments()
,
events()
,
locations()
,
media()
,
observations()
x <- example_dataset() taxa(x)
x <- example_dataset() taxa(x)
Extracts the version number used by a Camera Trap Data Package object. This version number indicates what version of the Camtrap DP standard was used.
version(x)
version(x)
x |
Camera Trap Data Package object, as returned by
|
The version number is derived as follows:
The version
attribute, if defined.
A version number contained in x$profile
, which is expected to
contain the URL to the used Camtrap DP standard.
x$profile
in its entirety (can be NULL
).
Camtrap DP version number (e.g. 1.0
).
x <- example_dataset() version(x)
x <- example_dataset() version(x)
Writes a Camera Trap Data Package and its related Data Resources to disk as a
datapackage.json
and CSV files.
write_camtrapdp(x, directory, ...)
write_camtrapdp(x, directory, ...)
x |
Camera Trap Data Package object, as returned by |
directory |
Path to local directory to write files to. |
... |
Further arguments, passed to |
datapackage.json
and CSV files written to disk.
x <- example_dataset() # Filter (and therefore change) the dataset x <- filter_deployments(x, deploymentID == "00a2c20d") # Write the Camera Trap Data Package to disk write_camtrapdp(x, directory = "my_directory") # Check files list.files("my_directory") # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)
x <- example_dataset() # Filter (and therefore change) the dataset x <- filter_deployments(x, deploymentID == "00a2c20d") # Write the Camera Trap Data Package to disk write_camtrapdp(x, directory = "my_directory") # Check files list.files("my_directory") # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)
Transforms a Camera Trap Data Package object to a Darwin Core Archive.
write_dwc(x, directory)
write_dwc(x, directory)
x |
Camera Trap Data Package object, as returned by |
directory |
Path to local directory to write files to. |
CSV and meta.xml
files written to disk.
And invisibly, a list of data frames with the transformed data.
This function follows recommendations in Reyserhove et al. (2023) doi:10.35035/doc-0qzp-2x37 and transform data to:
An Occurrence core.
A meta.xml
file.
Key features of the Darwin Core transformation:
The Occurrence core contains one row per observation
(dwc:occurrenceID = observationID
).
Only observations with observationType = "animal"
and
observationLevel = "event"
are included, thus excluding observations that
are (of) humans, vehicles, blanks, unknowns, unclassified and media-based.
Deployment information is included in the Occurrence core, such as
location, habitat, dwc:samplingProtocol
, deployment duration in
dwc:samplingEffort
and dwc:parentEventID = deploymentID
as grouping
identifier.
Event information is included in the Occurrence core, as event duration in
dwc:eventDate
and dwc:eventID = eventID
as grouping identifier.
Media files are included in the Audubon/Audiovisual Media Description extension, with a foreign key to the observation. A media file that is used for more than one observation is repeated.
Metadata are used to set the following record-level terms:
dwc:datasetID
: x$id
.
dwc:datasetName
: x$title
.
dwc:collectionCode
: first source in x$sources
.
dcterms:license
: license name
(e.g. CC0-1.0
) in x$licenses
with
scope data
.
The license name
with scope media
is used as dcterms:rights
in the
Audubon Media Description extension.
dcterms:rightsHolder
: first contributor in x$contributors
with role
rightsHolder
.
dwc:dataGeneralizations
: set if x$coordinatePrecision
is defined.
Other transformation functions:
round_coordinates()
,
shift_time()
,
write_eml()
x <- example_dataset() write_dwc(x, directory = "my_directory") # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)
x <- example_dataset() write_dwc(x, directory = "my_directory") # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)
Transforms the metadata of a Camera Trap Data Package object to an Ecological Metadata Language (EML) file.
write_eml(x, directory, derived_paragraph = TRUE)
write_eml(x, directory, derived_paragraph = TRUE)
x |
Camera Trap Data Package object, as returned by |
directory |
Path to local directory to write files to. |
derived_paragraph |
If |
eml.xml
file written to disk.
And invisibly, an EML::eml object.
Metadata are derived from what is provided in x
.
The following properties are set:
title: Title as provided in x$title
.
type: Set to Occurrence
in keywords.
subtype: Set to Observation
in keywords.
update frequency: Set to unknown
.
description: Description as provided in x$description
.
If derived_paragraph = TRUE
a generated paragraph is added, e.g.:
Data have been standardized to Darwin Core using the camtrapdp R package and only include observations (and associated media) of animals. Excluded are records that document blank or unclassified media, vehicles and observations of humans.
license: License with scope data
as provided in x$licenses
.
creators: Contributors (all roles) as provided in x$contributors
.
contact: Contributors with role contact
. If none exist, first
creator.
metadata provider: Same as contact
.
keywords: Keywords as provided in x$keywords
.
geographic coverage: Bounding box as provided in x$spatial
.
taxonomic coverage: Taxa as provided in x$taxonomic
.
temporal coverage: Date range as provided in x$temporal
.
project data: Title, acronym as identifier, description, and sampling
design as provided in x$project
.
alternative identifier: Identifier as provided in x$id
.
If this is a DOI, no new DOI will be created when publishing to GBIF.
external link: URL of the project as provided in
x$project$path
.
The following properties are not set:
publishing organization
associated parties
sampling methods
citations
collection data: not applicable.
Other transformation functions:
round_coordinates()
,
shift_time()
,
write_dwc()
x <- example_dataset() (write_eml(x, directory = "my_directory")) # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)
x <- example_dataset() (write_eml(x, directory = "my_directory")) # Clean up (don't do this if you want to keep your files) unlink("my_directory", recursive = TRUE)