knitr::opts_chunk$set(echo = TRUE)

Introduction

In this vignette we show a typical workflow using the etn package to retrieve acoustic telemetry data from ETN. We will also use the packages dplyr for data exploration, lubridate to handle datetime data and leaflet for interactive visualizations.

To start, load the etn package:

library(etn)

And the other packages (with installation if necessary):

other_pkgs <- c("dplyr", "lubridate", "leaflet")

# install missing packages
pkgs_to_install <- other_pkgs[!other_pkgs %in% rownames(installed.packages())]
install.packages(pkgs_to_install)

# load packages
library(dplyr)
library(lubridate)
library(leaflet)

Connect with your user credentials (as received by VLIZ) to the database. To not expose such confidential information, you could opt to use environment variables:

con <- connect_to_etn(Sys.getenv("userid"), Sys.getenv("pwd"))
# This is the default, so you could also use connect_to_etn()

Using con as variable to store the collection is not mandatory, but it makes your life much easier as con is the default value of the argument connection, present in every other function of this package.

Select project(s) of interest

A researcher typically works in the context of one or more animal projects. As the project codes are not always easy to remember, let's start by getting an overview of all projects:

all_projects <- get_animal_projects()

Show a preview:

all_projects %>% head(10)

If you know the project code already and you are just interested to get more information about it, you can specify it in the get_animal_projects() function directly:

projects_code <- c("2014_demer", "2015_dijle")
projects_study <- get_animal_projects(animal_project_code = projects_code)
projects_study

This is exactly the same as retrieving all projects first and filtering them afterwards based on column project_code:

all_projects %>%
  filter(project_code %in% c(projects_code))

To list all available animal project codes as a vector, you can use list_animal_project_codes(), one of the etn functions in the list_* family:

list_animal_project_codes() %>% head(10)

Animals

By using get_animals() you can retrieve information about each animal (animal_id), such as scientific name, length, capture/release date and location, and the attached tag(s) (tag_serial_number):

animals <- get_animals(animal_project_code = projects_code)
animals %>% head(10)

What species and how many individuals are tracked for the projects 2014_demer and 2015_dijle?

animals %>%
  count(scientific_name)

Detections

Let's say we are interested in the tracking data of Wels catfish (Silurus glanis) in 2014. You can retrieve the detection history using get_acoustic_detections():

detections_silurus <- get_acoustic_detections(
  animal_project_code = projects_code,
  start_date = "2014-01-01",
  end_date = "2015-01-01", # The end date is exclusive
  scientific_name = "Silurus glanis"
)

Preview:

detections_silurus %>% head(10)

Which individuals have been detected (animal_id) and in which period?

detections_silurus_period <-
  detections_silurus %>%
  mutate(date = date(date_time)) %>%
  group_by(animal_id) %>%
  summarize(
    start = min(date),
    end = max(date)
  )
detections_silurus_period

Notice we group by animal_id, the unique identifier of the fish. However, if the fish has only been tagged once (as typically occurs), we could use acoustic_tag_id as well, i.e. the identifier picked up by acoustic receivers:

detections_silurus %>%
  mutate(date = date(date_time)) %>%
  group_by(acoustic_tag_id) %>%
  summarize(
    start = min(date),
    end = max(date)
  )

We can also get the tracking duration of each fish:

detections_silurus_duration <-
  detections_silurus %>%
  group_by(animal_id) %>%
  summarize(duration = max(date_time) - min(date_time))
detections_silurus_duration

How many times has an individual has been detected?

detections_silurus %>%
  group_by(animal_id) %>%
  count()

Stations

At how many detection stations have the individuals been detected?

detections_silurus %>%
  group_by(animal_id) %>%
  distinct(station_name) %>%
  count()

Which stations have been involved? You can retrieve them using list_values function applied to column station_name:

stations_silurus <-
  detections_silurus %>%
  list_values(station_name)
stations_silurus

Notice how a detection station can be linked to multiple deployments:

detections_silurus %>%
  distinct(station_name, deployment_id) %>%
  group_by(station_name) %>%
  add_tally() %>%
  arrange(desc(n))

Sometimes it's interesting to know the number of detections per station:

n_detect_station <-
  detections_silurus %>%
  group_by(station_name) %>%
  count()
n_detect_station

It's also interesting to know the number of unique individuals per station:

n_silurus_station <-
  detections_silurus %>%
  distinct(station_name, animal_id) %>%
  group_by(station_name) %>%
  count()
n_silurus_station

Acoustic tags

To get more information about the tags involved in detections_silurus, you can use the function get_tags, which returns tag related information such as serial number, manufacturer, model, and frequency:

tags_id <- list_values(detections_silurus, acoustic_tag_id)
tags_silurus <- get_tags(acoustic_tag_id = tags_id)
tags_silurus

You can also retrieve such information by tag_serial_number:

tags_serial <- unique(detections_silurus$tag_serial_number)
tags_silurus <- get_tags(tag_serial_number = tags_serial)
tags_silurus

However, keep in mind that there is a fundamental difference between the arguments acoustic_tag_id and tag_serial_number: the tag_serial_number identifies the device, which could contain multiple tags or sensors and thus multiple acoustic_tag_id.

All possible acoustic_tag_id can be retrieved with the correspondent list_* function:

list_acoustic_tag_ids() %>% head(10)

Acoustic network projects

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():

acoustic_project_codes <- detections_silurus %>%
  list_values(acoustic_project_code)
acoustic_project_codes

To get more information about these acoustic networks, you can use function get_acoustic_projects()

acoustic_projects_silurus <- get_acoustic_projects(
  acoustic_project_code = acoustic_project_codes
)
acoustic_projects_silurus

You can retrieve the full list of acoustic network projects with the correspondent list_* function:

list_acoustic_project_codes() %>% head(10)

Acoustic deployments

You can retrieve deployment information related to the acoustic networks in acoustic_project_codes by using get_acoustic_deployments() function:

deployments <- get_acoustic_deployments(
  acoustic_project_code = acoustic_project_codes
)
deployments

These are the deployments of the acoustic receivers involved in detections_silurus:

deploys_silurus <-
  detections_silurus %>%
  list_values(deployment_id)
deploys_silurus

More information about them can be retrieved via get_acoustic_deployments() function with argument deployment_id:

deployments_silurus <- get_acoustic_deployments(
  deployment_id = deploys_silurus
)
deployments_silurus

Deployment duration:

deployments_silurus_duration <-
  deployments_silurus %>%
  mutate(duration = as.duration(recover_date_time - deploy_date_time)) %>%
  select(deployment_id, station_name, duration) %>%
  arrange(deployment_id)
deployments_silurus_duration

Number of days a deployment detected the passage of one or more individuals:

n_active_days_deployments_silurus <-
  detections_silurus %>%
  mutate(date = date(date_time)) %>%
  distinct(deployment_id, station_name, date) %>%
  group_by(deployment_id, station_name) %>%
  summarize(n_days = n(), .groups = "drop") %>%
  ungroup()
n_active_days_deployments_silurus

Relative detection duration, i.e. number of days with at least one detection divided by deployment duration:

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)
  ) %>%
  select(deployment_id, station_name, relative_detection_duration)
rel_det_duration_silurus

Data visualization

Aside standard graphs, the geographical component of telemetry data makes interactive maps particularly useful. The package leaflet is quite popular to create such kind of visualizations.

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:

geo_info_stations <-
  detections_silurus %>%
  distinct(
    station_name,
    deploy_latitude,
    deploy_longitude,
    acoustic_project_code
  ) %>%
  arrange(station_name)
geo_info_stations

To be able to produce the desired map:

leaflet(geo_info_stations) %>%
  addTiles() %>%
  addMarkers(
    lng = ~deploy_longitude,
    lat = ~deploy_latitude,
    popup = ~paste0("Station: ", station_name, " (", acoustic_project_code, ")")
  )

We can visualize the number of detections per station, n_detect_station, by joining it with geo_info_stations:

# Create a continuous colour palette function
pal <- colorNumeric(
  palette = "viridis",
  domain = n_detect_station$n
)

n_detect_station %>%
  left_join(
    geo_info_stations,
    by = "station_name"
  ) %>%
  leaflet() %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~deploy_longitude,
    lat = ~deploy_latitude,
    radius = ~log(n),
    color = ~pal(n),
    fillOpacity = 0.8,
    stroke = FALSE,
    popup = ~paste(
      sep = "<br/>",
      paste0("Station: ", station_name, " (", acoustic_project_code, ")"),
      paste0("# detections: ", n)
    )
  ) %>%
  addLegend(
    title = "Detections",
    pal = pal,
    values = ~n
  )

In a similar way we can visualize the number of detected individuals per station, n_silurus_station:

# Create a continuous colour palette function
pal <- colorNumeric(
  palette = "viridis",
  domain = n_silurus_station$n
)

n_silurus_station %>%
  left_join(
    geo_info_stations,
    by = "station_name"
  ) %>%
  leaflet() %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~deploy_longitude,
    lat = ~deploy_latitude,
    radius = ~n,
    color = ~pal(n),
    fillOpacity = 0.8,
    stroke = FALSE,
    popup = ~paste(
      sep = "<br/>",
      paste0("Station: ", station_name, " (", acoustic_project_code, ")"),
      paste0("# detected individuals: ", n)
    )
  ) %>%
  addLegend(
    title = "Detected individuals",
    pal = pal,
    values = ~n
  )

We can also make a map of the relative detection duration of the deployments. First, we have to retrieve the deployment geographical coordinates:

geo_info_deploys <-
  detections_silurus %>%
  distinct(
    deployment_id,
    deploy_latitude,
    deploy_longitude,
    station_name,
    acoustic_project_code
  ) %>%
  arrange(station_name)
geo_info_deploys

We are ready to create the desired map, where we show the deployment ID, the station name and the network project as popups:

# Create a continuous colour palette function
pal <- colorNumeric(
  palette = "viridis",
  domain = rel_det_duration_silurus$relative_detection_duration
)

rel_det_duration_silurus %>%
  left_join(
    geo_info_deploys,
    by = c("deployment_id", "station_name")
  ) %>%
  leaflet() %>%
  addTiles() %>%
  addCircleMarkers(
    lng = ~deploy_longitude,
    lat = ~deploy_latitude,
    radius = ~100 * relative_detection_duration,
    color = ~pal(relative_detection_duration),
    fillOpacity = 0.8,
    stroke = FALSE,
    clusterOptions = markerClusterOptions(),
    popup = ~paste(
      sep = "<br/>",
      paste0("DeploymentID: ", deployment_id),
      paste0("Station: ", station_name, " (", acoustic_project_code, ")"),
      paste0("# relative detection duration: ", round(relative_detection_duration, 2))
    )
  ) %>%
  addLegend(
    title = "Relative detection duration",
    pal = pal,
    values = ~relative_detection_duration
  )

Do you want to add the temporal component to visualize the fish movement? Take a look at the moveVis package.



inbo/etn documentation built on Dec. 5, 2023, 4:17 a.m.