43 Appendix: Tracking data: advanced interpolation
This chapter uses previously filtered data. It is still a work in progress :)
NOTE: if your animal visits land at several other locations beyond the colony, you may need to consider appropriate action for more advanced interpolation methods.
43.1 Goal of chapter:
Support further cleaning of tracking data by applying speed filters and interpolation methods.
43.2 Interpolation
If you have gaps in your tracking data, you need to fill these gaps for the purpose of the track2KBA protocol. It’s likely you will need to do this for many other tracking data analyses.
Broadly speaking, there are two key ways to fill the gaps in your tracking data, a process known as interpolation.
These two ways include: - Simpler linear interpolation - More advanced interpolation options that try account for where the animal could have moved (e.g. CRAWL)
Typically, for flying seabirds, where gaps in tracking data are less likely because birds do not typically dive underwater for durations as long as diving seabirds, linear interpolation should serve as a suitable starting point.
More advanced interpolation methods may be required for diving seabirds, or other diving marine predators.
43.3 Load packages
Load required R packages:
If the package(s) fails to load, you will need to install the relevant package(s).
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Load libraries --------------------------------------------------------------
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"Had to install R version: R version 4.2.2 (2022-10-31 ucrt) for aniMotum"
## [1] "Had to install R version: R version 4.2.2 (2022-10-31 ucrt) for aniMotum"
## Options to install aniMotum package for animal track interpolation
## aniMotum: https://besjournals.onlinelibrary.wiley.com/doi/10.1111/2041-210X.14060
#install.packages('aniMotum', repos = c('https://ianjonsen.r-universe.dev', 'https://cloud.r-project.org'))
# may need to install aniMotum after downloading using: devtools::install_local(package.zip)
#install.packages('TMB', type = 'source')
library("aniMotum")
## sf package for spatial data analyses (i.e. vector files such as points, lines, polygons)
library(sf)
## Tidyverse for data manipulation
library(tidyverse)
## ggplot2 for plotting opionts
library(ggplot2)
## rnaturalearth package for basemaps in R
library(rnaturalearth)
## leaflet package for interactive maps in R
#install.packages("leaflet")
library(leaflet)
##
library(purrr)
library(furrr)
#install.packages("track2KBA")
library(track2KBA)
## for date time
library(lubridate)
## for stats
library(stats)
## speed filter
library(trip)
## linear interpolation
library(adehabitatLT)
43.4 Input parameters for chapter tutorial
Here we define input parameters needed for sections of the code later in this tutorial.
Depending on how your data is set up, you should not need to define any further input parameters.
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Specify projections / store needed CRS definitions as variables ----
## SEE: https://epsg.io/
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## world - unprojected coordinates
wgs84 <- st_crs("EPSG:4326")
## Croatia - projected coordinates
htrs96 <- st_crs("EPSG:3765")
## Source a world map from the rnaturalearth R package
## see details of function to change the type of map you get
worldmap <- rnaturalearth::ne_download(scale = "large",
type = "countries",
category = "cultural",
destdir = tempdir(),
load = TRUE,
returnclass = "sf")
## Reading layer `ne_10m_admin_0_countries' from data source
## `C:\Users\jonathan.handley\AppData\Local\Temp\Rtmp6L566o\ne_10m_admin_0_countries.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 258 features and 168 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -180 ymin: -90 xmax: 180 ymax: 83.63410065
## Geodetic CRS: WGS 84
43.5 Load input example data and prepare for track2KBA R package protocol
Loading the input example data
## Load the example data for Yelkouan Shearwaters
load("data-testing/tracking-data/Tracking_YESH_raw_step3.Rdata")
## view the first two rows of data
## First view the data in tibble format
#head(tracks,2)
## Then view the data in data frame format
head(data.frame(tracks),2)
## dataset_id scientific_name common_name site_name colony_name
## 8 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 9 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 8 tbc tbc GPS 19_Tag17600_Z-9 19_Tag17600_Z-9
## 9 tbc tbc GPS 19_Tag17600_Z-9 19_Tag17600_Z-9
## original_track_id age sex breed_stage breed_status date_gmt
## 8 19_Tag17600_Z-9 adult unknown chick-rearing breeding 2019-05-24
## 9 19_Tag17600_Z-9 adult unknown chick-rearing breeding 2019-05-24
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 8 03:09:05 NA NA 2019-05-24 03:09:05 15 16.875686
## 9 03:29:05 NA NA 2019-05-24 03:29:05 15 16.842989
## Latitude nlocs track_segment track_colour DateTime
## 8 42.863631 8 track.start #66c2a5 2019-05-24 03:09:05
## 9 42.889146 9 track.start #66c2a5 2019-05-24 03:29:05
## tripID X Y Returns StartsOut ColDist
## 8 19_Tag17600_Z-9_01 16.875686 42.863631 Yes 5843.849769
## 9 19_Tag17600_Z-9_01 16.842989 42.889146 Yes 9297.406605
## dataGroup.Longitude dataGroup.Latitude optional
## 8 16.875686 42.863631 TRUE
## 9 16.842989 42.889146 TRUE
43.6 Interpolation methods differences
We will consider some of the different interpolation methods:
- Linear interpolation
- CRAWL interpolation
43.6.1 Get example data for testing
Based on some previous exploration of the data, here are some individual trips that provide a basis of example data to understand impact of different inteprolation methods.
NOTE to JONO: Consider impact of previous buffer choice on selection of final number of trips.
[Should we apply relative at-sea buffer at the tripSplit step or later on. Later seems to make sense to me. But this also means we might remove what are considered invidual trips if we increase the buffer size.]
## [1] 339
Example trips to try:
278: a good track. Although technically colony location might be wrong given buffer applied above.
305: a good track. Seems feasible.
339: a track that goes over land supposedly.
252: dodgey track with too few points most likely.
210: reasonable track, but some big gaps in data likely when birds commuting.
273: obvious location error with single point extremely far away.”
Change the input parameter below to select a new unique trip
## Input parameter for selecting unique trips
i= 273
## subset the data from a unique trip
bird_track <- data.frame(tracks) %>% dplyr::filter(tripID == unique(tracks$tripID)[i])
## add a column indicating start and end of tracks
bird_track <- bird_track %>% mutate(nlocs = 1:nrow(bird_track)) %>%
mutate(track_segment = if_else(nlocs <= 10, "track.start","track.journey")) %>%
## note: if you have a track with less than 20 points, then you will overwrite
## some of the previous data.
mutate(track_segment = if_else(nlocs %in% (nrow(bird_track)-9):(nrow(bird_track)),"track.end",track_segment)) %>%
## add a column indicating colour for start and end of tracks
## colours from: https://colorbrewer2.org/#type=qualitative&scheme=Set2&n=3
mutate(track_colour = if_else(nlocs <= 10, "#66c2a5","#8da0cb")) %>%
mutate(track_colour = if_else(nlocs %in% (nrow(bird_track)-9):(nrow(bird_track)),"#fc8d62",track_colour))
head(data.frame(bird_track),12)
## dataset_id scientific_name common_name site_name colony_name
## 1 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 2 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 3 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 4 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 5 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 6 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 7 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 8 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 9 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 10 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 11 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 12 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 1 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 2 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 3 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 4 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 5 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 6 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 7 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 8 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 9 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 10 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 11 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 12 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## original_track_id age sex breed_stage breed_status date_gmt
## 1 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 2 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 3 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 4 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 5 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 6 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 7 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 8 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 9 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 10 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 11 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 12 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 1 00:41:02 NA NA 2020-05-23 00:41:02 27 16.873765
## 2 02:00:55 NA NA 2020-05-23 02:00:55 27 16.976549
## 3 02:40:55 NA NA 2020-05-23 02:40:55 27 16.977327
## 4 03:21:00 NA NA 2020-05-23 03:21:00 27 17.065564
## 5 04:01:09 NA NA 2020-05-23 04:01:09 27 17.399801
## 6 04:56:05 NA NA 2020-05-23 04:56:05 27 17.772279
## 7 05:40:22 NA NA 2020-05-23 05:40:22 27 17.787105
## 8 06:25:59 NA NA 2020-05-23 06:25:59 27 17.792098
## 9 07:41:36 NA NA 2020-05-23 07:41:36 27 17.791651
## 10 09:27:30 NA NA 2020-05-23 09:27:30 27 17.792932
## 11 10:57:03 NA NA 2020-05-23 10:57:03 27 17.782182
## 12 11:43:08 NA NA 2020-05-23 11:43:08 27 17.779680
## Latitude nlocs track_segment track_colour DateTime
## 1 42.775604 1 track.start #66c2a5 2020-05-23 00:41:02
## 2 42.837699 2 track.start #66c2a5 2020-05-23 02:00:55
## 3 42.837664 3 track.start #66c2a5 2020-05-23 02:40:55
## 4 42.857446 4 track.start #66c2a5 2020-05-23 03:21:00
## 5 42.844356 5 track.start #66c2a5 2020-05-23 04:01:09
## 6 42.736141 6 track.start #66c2a5 2020-05-23 04:56:05
## 7 42.735978 7 track.start #66c2a5 2020-05-23 05:40:22
## 8 42.737175 8 track.start #66c2a5 2020-05-23 06:25:59
## 9 42.737054 9 track.start #66c2a5 2020-05-23 07:41:36
## 10 42.729099 10 track.start #66c2a5 2020-05-23 09:27:30
## 11 42.736360 11 track.journey #8da0cb 2020-05-23 10:57:03
## 12 42.735342 12 track.journey #8da0cb 2020-05-23 11:43:08
## tripID X Y Returns StartsOut ColDist
## 1 20_Tag40118_Z-175_10 16.873765 42.775604 Yes 4236.43456
## 2 20_Tag40118_Z-175_10 16.976549 42.837699 Yes 10399.61143
## 3 20_Tag40118_Z-175_10 16.977327 42.837664 Yes 10459.51519
## 4 20_Tag40118_Z-175_10 17.065564 42.857446 Yes 17999.32080
## 5 20_Tag40118_Z-175_10 17.399801 42.844356 Yes 44730.44513
## 6 20_Tag40118_Z-175_10 17.772279 42.736141 Yes 75558.63900
## 7 20_Tag40118_Z-175_10 17.787105 42.735978 Yes 76766.77599
## 8 20_Tag40118_Z-175_10 17.792098 42.737175 Yes 77158.00160
## 9 20_Tag40118_Z-175_10 17.791651 42.737054 Yes 77123.13324
## 10 20_Tag40118_Z-175_10 17.792932 42.729099 Yes 77331.29092
## 11 20_Tag40118_Z-175_10 17.782182 42.736360 Yes 76361.42790
## 12 20_Tag40118_Z-175_10 17.779680 42.735342 Yes 76170.90183
## dataGroup.Longitude dataGroup.Latitude optional
## 1 16.873765 42.775604 TRUE
## 2 16.976549 42.837699 TRUE
## 3 16.977327 42.837664 TRUE
## 4 17.065564 42.857446 TRUE
## 5 17.399801 42.844356 TRUE
## 6 17.772279 42.736141 TRUE
## 7 17.787105 42.735978 TRUE
## 8 17.792098 42.737175 TRUE
## 9 17.791651 42.737054 TRUE
## 10 17.792932 42.729099 TRUE
## 11 17.782182 42.736360 TRUE
## 12 17.779680 42.735342 TRUE
## dataset_id scientific_name common_name site_name colony_name
## 281 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 282 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 283 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 284 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 285 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 286 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 287 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 288 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 289 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 290 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 291 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 292 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 281 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 282 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 283 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 284 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 285 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 286 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 287 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 288 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 289 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 290 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 291 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 292 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## original_track_id age sex breed_stage breed_status date_gmt
## 281 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 282 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 283 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 284 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 285 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 286 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 287 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 288 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 289 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 290 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 291 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## 292 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-06-04
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 281 09:14:25 NA NA 2020-06-04 09:14:25 27 16.889855
## 282 10:01:50 NA NA 2020-06-04 10:01:50 27 16.882272
## 283 10:23:26 NA NA 2020-06-04 10:23:26 27 16.886676
## 284 10:46:20 NA NA 2020-06-04 10:46:20 27 16.936658
## 285 11:16:16 NA NA 2020-06-04 11:16:16 27 16.934755
## 286 12:02:24 NA NA 2020-06-04 12:02:24 27 16.911330
## 287 12:26:12 NA NA 2020-06-04 12:26:12 27 16.880714
## 288 12:46:32 NA NA 2020-06-04 12:46:32 27 16.881518
## 289 13:09:53 NA NA 2020-06-04 13:09:53 27 16.890075
## 290 14:23:01 NA NA 2020-06-04 14:23:01 27 16.883198
## 291 16:02:15 NA NA 2020-06-04 16:02:15 27 16.628421
## 292 20:17:21 NA NA 2020-06-04 20:17:21 27 16.700074
## Latitude nlocs track_segment track_colour DateTime
## 281 43.247558 281 track.journey #8da0cb 2020-06-04 09:14:25
## 282 43.246526 282 track.journey #8da0cb 2020-06-04 10:01:50
## 283 43.184219 283 track.end #fc8d62 2020-06-04 10:23:26
## 284 43.219847 284 track.end #fc8d62 2020-06-04 10:46:20
## 285 43.227534 285 track.end #fc8d62 2020-06-04 11:16:16
## 286 43.253257 286 track.end #fc8d62 2020-06-04 12:02:24
## 287 43.194572 287 track.end #fc8d62 2020-06-04 12:26:12
## 288 43.179669 288 track.end #fc8d62 2020-06-04 12:46:32
## 289 43.175502 289 track.end #fc8d62 2020-06-04 13:09:53
## 290 43.181891 290 track.end #fc8d62 2020-06-04 14:23:01
## 291 43.239596 291 track.end #fc8d62 2020-06-04 16:02:15
## 292 42.866379 292 track.end #fc8d62 2020-06-04 20:17:21
## tripID X Y Returns StartsOut ColDist
## 281 20_Tag40118_Z-175_10 16.889855 43.247558 Yes 48579.34946
## 282 20_Tag40118_Z-175_10 16.882272 43.246526 Yes 48432.22494
## 283 20_Tag40118_Z-175_10 16.886676 43.184219 Yes 41539.87847
## 284 20_Tag40118_Z-175_10 16.936658 43.219847 Yes 45905.38549
## 285 20_Tag40118_Z-175_10 16.934755 43.227534 Yes 46728.46321
## 286 20_Tag40118_Z-175_10 16.911330 43.253257 Yes 49344.41695
## 287 20_Tag40118_Z-175_10 16.880714 43.194572 Yes 42660.85256
## 288 20_Tag40118_Z-175_10 16.881518 43.179669 Yes 41010.77314
## 289 20_Tag40118_Z-175_10 16.890075 43.175502 Yes 40592.20978
## 290 20_Tag40118_Z-175_10 16.883198 43.181891 Yes 41264.78385
## 291 20_Tag40118_Z-175_10 16.628421 43.239596 Yes 51055.50065
## 292 20_Tag40118_Z-175_10 16.700074 42.866379 Yes 14052.11191
## dataGroup.Longitude dataGroup.Latitude optional
## 281 16.889855 43.247558 TRUE
## 282 16.882272 43.246526 TRUE
## 283 16.886676 43.184219 TRUE
## 284 16.936658 43.219847 TRUE
## 285 16.934755 43.227534 TRUE
## 286 16.911330 43.253257 TRUE
## 287 16.880714 43.194572 TRUE
## 288 16.881518 43.179669 TRUE
## 289 16.890075 43.175502 TRUE
## 290 16.883198 43.181891 TRUE
## 291 16.628421 43.239596 TRUE
## 292 16.700074 42.866379 TRUE
## plot the tracks using leaflet package in R.
map <- leaflet() %>% ## start leaflet plot
addProviderTiles(providers$Esri.WorldImagery, group = "World Imagery") %>%
## plot the points. Note: leaflet automatically finds lon / lat colonies
## label by nloc (location) number. Colour accordingly.
addCircleMarkers(data = bird_track,
label = bird_track$nlocs, radius = 3,
fillColor = bird_track$track_colour,
fillOpacity = 0.5, stroke = F) %>%
## plot lines between points
addPolylines(lng = bird_track$Longitude,
lat = bird_track$Latitude, weight = 1,
color = "white")
map
43.7 Speed filter & linear interpolation
First apply the simpler cleaning step to the data:
McConnel Speed Filter (i.e. remove points based on unrealistic travel speeds)
Linear interpolation (i.e. add missing points on a straight line between known points)
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Speed filter / linear interpolation ----
## For flying seabirds: CRAWL may not be best bet - linear interpolation may be better."
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## review example data
head(bird_track,2)
## dataset_id scientific_name common_name site_name colony_name
## 1 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 2 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 1 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 2 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## original_track_id age sex breed_stage breed_status date_gmt
## 1 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 2 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 1 00:41:02 NA NA 2020-05-23 00:41:02 27 16.873765
## 2 02:00:55 NA NA 2020-05-23 02:00:55 27 16.976549
## Latitude nlocs track_segment track_colour DateTime
## 1 42.775604 1 track.start #66c2a5 2020-05-23 00:41:02
## 2 42.837699 2 track.start #66c2a5 2020-05-23 02:00:55
## tripID X Y Returns StartsOut ColDist
## 1 20_Tag40118_Z-175_10 16.873765 42.775604 Yes 4236.43456
## 2 20_Tag40118_Z-175_10 16.976549 42.837699 Yes 10399.61143
## dataGroup.Longitude dataGroup.Latitude optional
## 1 16.873765 42.775604 TRUE
## 2 16.976549 42.837699 TRUE
## remove any erroneous locations due to speed use the McConnel Speed Filter
##from the trip package
trip_obj <- bird_track %>%
#group_by(tripID) %>%
dplyr::select(x = X,
y = Y,
DateTime,
everything()) %>%
trip()
head(trip_obj,2)
## DateTime dataset_id scientific_name common_name
## 1 2020-05-23 00:41:02 tbc Puffinus yelkouan Yelkouan Shearwater
## 2 2020-05-23 02:00:55 tbc Puffinus yelkouan Yelkouan Shearwater
## site_name colony_name lat_colony lon_colony device ID
## 1 Lastovo SPA Z tbc tbc GPS 20_Tag40118_Z-175
## 2 Lastovo SPA Z tbc tbc GPS 20_Tag40118_Z-175
## track_id original_track_id age sex breed_stage breed_status
## 1 20_Tag40118_Z-175 20_Tag40118_Z-175 adult unknown chick-rearing breeding
## 2 20_Tag40118_Z-175 20_Tag40118_Z-175 adult unknown chick-rearing breeding
## date_gmt time_gmt argos_quality equinox dttm bird_id_num
## 1 2020-05-23 00:41:02 NA NA 2020-05-23 00:41:02 27
## 2 2020-05-23 02:00:55 NA NA 2020-05-23 02:00:55 27
## Longitude Latitude nlocs track_segment track_colour tripID
## 1 16.873765 42.775604 1 track.start #66c2a5 20_Tag40118_Z-175_10
## 2 16.976549 42.837699 2 track.start #66c2a5 20_Tag40118_Z-175_10
## Returns StartsOut ColDist dataGroup.Longitude dataGroup.Latitude optional
## 1 Yes 4236.43456 16.873765 42.775604 TRUE
## 2 Yes 10399.61143 16.976549 42.837699 TRUE
## McConnel Speedilter -----
## apply speedfilter and creat data frame
trip_obj$Filter <- speedfilter(trip_obj, max.speed = 100) # speed in km/h
trip_obj <- data.frame(trip_obj)
head(trip_obj,2)
## x y DateTime dataset_id scientific_name
## 1 16.873765 42.775604 2020-05-23 00:41:02 tbc Puffinus yelkouan
## 2 16.976549 42.837699 2020-05-23 02:00:55 tbc Puffinus yelkouan
## common_name site_name colony_name lat_colony lon_colony device
## 1 Yelkouan Shearwater Lastovo SPA Z tbc tbc GPS
## 2 Yelkouan Shearwater Lastovo SPA Z tbc tbc GPS
## ID track_id original_track_id age sex
## 1 20_Tag40118_Z-175 20_Tag40118_Z-175 20_Tag40118_Z-175 adult unknown
## 2 20_Tag40118_Z-175 20_Tag40118_Z-175 20_Tag40118_Z-175 adult unknown
## breed_stage breed_status date_gmt time_gmt argos_quality equinox
## 1 chick-rearing breeding 2020-05-23 00:41:02 NA NA
## 2 chick-rearing breeding 2020-05-23 02:00:55 NA NA
## dttm bird_id_num Longitude Latitude nlocs track_segment
## 1 2020-05-23 00:41:02 27 16.873765 42.775604 1 track.start
## 2 2020-05-23 02:00:55 27 16.976549 42.837699 2 track.start
## track_colour tripID Returns StartsOut ColDist
## 1 #66c2a5 20_Tag40118_Z-175_10 Yes 4236.43456
## 2 #66c2a5 20_Tag40118_Z-175_10 Yes 10399.61143
## dataGroup.Longitude dataGroup.Latitude optional Filter optional.1
## 1 16.873765 42.775604 TRUE TRUE TRUE
## 2 16.976549 42.837699 TRUE TRUE TRUE
## [1] 1
## plot the original data AND McConnel speed filtered removed values
map %>% addCircleMarkers(data = subset(trip_obj, trip_obj$Filter == F),
#label = bird_track_gaps$nlocs,
radius = 5,
fillColor = "black",
fillOpacity = 0.5, stroke = F) %>%
addLegend(colors = "black",
labels = "McConnel removed values")
## [1] 292 38
## [1] 292 36
## [1] 291 38
## Linear interpolation -----
## Apply linear interpolation step to speed filtered only data
## create ltraj object
trip_lt <- as.ltraj(xy = bind_cols(x = trip_obj$x,
y = trip_obj$y),
date = trip_obj$DateTime,
id = trip_obj$tripID)
## Linearly interpolate/re-sample tracks every 30 minutes (specified in seconds)
trip_interp <- redisltraj(trip_lt, 1800, type="time")
head(trip_interp)
##
## *********** List of class ltraj ***********
##
## Type of the traject: Type II (time recorded)
## * Time zone: UTC *
## Regular traject. Time lag between two locs: 1800 seconds
##
## Characteristics of the bursts:
## id burst nb.reloc NAs date.begin
## 1 20_Tag40118_Z-175_10 20_Tag40118_Z-175_10 616 0 2020-05-23 00:41:02
## date.end
## 1 2020-06-04 20:11:02
##
##
## infolocs provided. The following variables are available:
## [1] "pkey"
## convert back into format for track2KBA - dataframe for now
trip_interp <- ld(trip_interp) %>%
dplyr::mutate(Longitude = x,
Latitude = y)
head(trip_interp,2)
## x y date dx dy
## 1 16.87376500 42.77560400 2020-05-23 00:41:02 0.03860029209 0.0233196328
## 2 16.91236529 42.79892363 2020-05-23 01:11:02 0.03860029209 0.0233196328
## dist dt R2n abs.angle rel.angle id
## 1 0.04509753678 1800 0.000000000000 0.5434514602 NA 20_Tag40118_Z-175_10
## 2 0.04509753678 1800 0.002033787823 0.5434514602 0 20_Tag40118_Z-175_10
## burst pkey Longitude
## 1 20_Tag40118_Z-175_10 20_Tag40118_Z-175_10.2020-05-23 00:41:02 16.87376500
## 2 20_Tag40118_Z-175_10 20_Tag40118_Z-175_10.2020-05-23 01:11:02 16.91236529
## Latitude
## 1 42.77560400
## 2 42.79892363
[CONSIDER BEST WAY TO ADD RELATED METADATA BACK. Holding script below for now]
## [1] "update"
#head(tracks_yelk)
#yelk_interp <- yelk_interp %>% dplyr::select(X = x,Y =y, DateTime = date, ID = id)
## update metadata that was lost during interpolation steps
"update"
## [1] "update"
#yelk_meta <- tracks_yelk %>%
# data.frame() %>%
# dplyr::select(ID, colony_code) %>%
# distinct(ID, colony_code)
## update for track2KBA
"update"
## [1] "update"
43.8 Plot: speed filtered and linear interpolation data
## plot speedfilter & linear interpolation
map %>% ## Speed Filtered and Linear interpolated
addCircleMarkers(data = trip_interp,
#label = bird_track$nlocs,
radius = 3,
fillColor = "cyan",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between Speed Filtered and Linear interpolated points
addPolylines(lng = trip_interp$Longitude,
lat = trip_interp$Latitude, weight = 1,
color = "cyan")
[Review advice on whether linear interpolation is suitable]
43.9 Advanced interpolation
[Possibly need to move this to appendix instead. Consider feedback]
Advanced interpolation methods such as CRAWL have been simplified with the aniMotum
R package.
We will apply the steps in the aniMotum
R package to apply CRAWL interpolation to the data.
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 1: Format the data"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## dataset_id scientific_name common_name site_name colony_name
## 1 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 2 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 1 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 2 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## original_track_id age sex breed_stage breed_status date_gmt
## 1 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 2 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 1 00:41:02 NA NA 2020-05-23 00:41:02 27 16.873765
## 2 02:00:55 NA NA 2020-05-23 02:00:55 27 16.976549
## Latitude nlocs track_segment track_colour DateTime
## 1 42.775604 1 track.start #66c2a5 2020-05-23 00:41:02
## 2 42.837699 2 track.start #66c2a5 2020-05-23 02:00:55
## tripID X Y Returns StartsOut ColDist
## 1 20_Tag40118_Z-175_10 16.873765 42.775604 Yes 4236.43456
## 2 20_Tag40118_Z-175_10 16.976549 42.837699 Yes 10399.61143
## dataGroup.Longitude dataGroup.Latitude optional
## 1 16.873765 42.775604 TRUE
## 2 16.976549 42.837699 TRUE
## format the data into format required for aniMotum
## NOTE: The format varies for Argos, GPS and GLS data - format accordingly
bird_track_am <- bird_track %>% mutate(lc = "G") %>%
dplyr::select(id = "tripID",
date = "dttm",
lc,
lon = "Longitude",
lat = "Latitude")
## review the newly formatted data
head(bird_track_am,20)
## id date lc lon lat
## 1 20_Tag40118_Z-175_10 2020-05-23 00:41:02 G 16.873765 42.775604
## 2 20_Tag40118_Z-175_10 2020-05-23 02:00:55 G 16.976549 42.837699
## 3 20_Tag40118_Z-175_10 2020-05-23 02:40:55 G 16.977327 42.837664
## 4 20_Tag40118_Z-175_10 2020-05-23 03:21:00 G 17.065564 42.857446
## 5 20_Tag40118_Z-175_10 2020-05-23 04:01:09 G 17.399801 42.844356
## 6 20_Tag40118_Z-175_10 2020-05-23 04:56:05 G 17.772279 42.736141
## 7 20_Tag40118_Z-175_10 2020-05-23 05:40:22 G 17.787105 42.735978
## 8 20_Tag40118_Z-175_10 2020-05-23 06:25:59 G 17.792098 42.737175
## 9 20_Tag40118_Z-175_10 2020-05-23 07:41:36 G 17.791651 42.737054
## 10 20_Tag40118_Z-175_10 2020-05-23 09:27:30 G 17.792932 42.729099
## 11 20_Tag40118_Z-175_10 2020-05-23 10:57:03 G 17.782182 42.736360
## 12 20_Tag40118_Z-175_10 2020-05-23 11:43:08 G 17.779680 42.735342
## 13 20_Tag40118_Z-175_10 2020-05-23 12:23:14 G 17.779476 42.734154
## 14 20_Tag40118_Z-175_10 2020-05-23 13:03:13 G 17.772935 42.740455
## 15 20_Tag40118_Z-175_10 2020-05-23 13:43:13 G 17.768276 42.744929
## 16 20_Tag40118_Z-175_10 2020-05-23 15:52:24 G 17.807283 42.725885
## 17 20_Tag40118_Z-175_10 2020-05-23 16:44:49 G 17.798066 42.731225
## 18 20_Tag40118_Z-175_10 2020-05-23 17:24:49 G 17.569362 42.764891
## 19 20_Tag40118_Z-175_10 2020-05-23 20:28:07 G 16.896792 42.804893
## 20 20_Tag40118_Z-175_10 2020-05-24 01:49:27 G 16.888790 42.788237
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 2: Fit the model"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "When fitting the model, there are some useful parameters to consider"
## fit the state-space model
## SEE the help file: ?fit_ssm, to understand some of the arguments within the function
## NOTE: the function can do 3 things simultaneously: data formatting step, a pre-filtering step, and the actual model fitting
## INPUT: data.frame, tibble or sf-tibble of observations, depending on the tracking data type
fit <- fit_ssm(bird_track_am,
## specify what kind of model you want to fit. See details about different model types in paper.
model = "crw",
## specify the speed at which data points could be considered outlier points (in m/s)
vmax = 27,
## time.step in hours - specify time.step of new values to be predicted (interpolation)
time.step = 0.5,
## turning angle/s in degrees. remove locations with turning angles set between intervals
## default values are not 0,0 (which will not do anything), but rather 15,25
ang = c(0, 0),
## step lengths in km - check implications for GPS vs. Argos data filtering
## defaults 2500,5000
distlim = c(2500, 5000))
## fitting crw SSM to 1 tracks...
##
pars: 0 0 0 0
pars: 0.93008 0.30696 0.20177 -0.00299
pars: 1.88497 0.03116 0.0922 -0.01351
pars: 3.44545 -1.23135 -0.56662 -0.02755
pars: 4.20599 -2.35909 -2.17381 0.14558
pars: 4.71635 -1.66561 -4.10041 0.24591
pars: 5.2144 -1.41556 -5.48667 0.34885
pars: 5.54323 -1.66357 -5.96781 0.40455
pars: 5.71782 -2.18086 -5.84244 0.42465
pars: 5.77391 -2.71252 -5.44297 0.4225
pars: 5.77391 -2.71252 -5.44297 0.4225
"NOTE: Depending on how you prefilter your data before running fit_ssm, you may
want to consider changing some of the function parameters. E.g. you might indicate
fit.to.subset = F, if you have filtered your data already and are sure all your
locations are true locations."
## [1] "NOTE: Depending on how you prefilter your data before running fit_ssm, you may\nwant to consider changing some of the function parameters. E.g. you might indicate\nfit.to.subset = F, if you have filtered your data already and are sure all your \nlocations are true locations."
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 3: Review the model fit"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## review the model summary
## See: https://ianjonsen.github.io/aniMotum/articles/Overview.html
"Check that converged and phHess were True. NOTE: I'm not sure what it means if they are false"
## [1] "Check that converged and phHess were True. NOTE: I'm not sure what it means if they are false"
## # A tibble: 1 × 5
## id ssm converged pdHess pmodel
## <chr> <named list> <lgl> <lgl> <chr>
## 1 20_Tag40118_Z-175_10 <ssm [15]> TRUE TRUE crw
"Review overall summaries and SSM details for each individual. Again, not entirely sure what all the important bits are"
## [1] "Review overall summaries and SSM details for each individual. Again, not entirely sure what all the important bits are"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 4: Review the different tabular ouputs after fitting the model"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## data.frame of SSM fitted values (location estimates corresponding to the observation times)
floc.fitted <- grab(fit, what = "fitted")
## data.frame of predicted values (corresponding to locations predicted at regular time.step intervals)
floc.predicted <- grab(fit, what = "predicted")
## data.frame of original data with a column indicating which locations to keep or not
floc.data <- grab(fit, what = "data")
## review the new data frames you get and your original data
head(data.frame(floc.fitted),2)
## id date lon lat x
## 1 20_Tag40118_Z-175_10 2020-05-23 00:41:02 16.87376504 42.775604 1878.378932
## 2 20_Tag40118_Z-175_10 2020-05-23 02:00:55 16.97654894 42.837699 1889.820784
## y x.se y.se u v
## 1 5248.851500 0.002867360468 0.0004212185085 0.009405468279 0.007483220442
## 2 5258.239344 0.006636952156 0.0004326470664 6.551973003306 5.625237176649
## u.se v.se s s.se
## 1 0.5970948485 0.594493515 1.856746356e-314 NA
## 2 9.5691434047 9.569135863 1.111640309e+01 NA
## id date lon lat x
## 1 20_Tag40118_Z-175_10 2020-05-23 00:41:00 16.87376500 42.77560400 1878.378928
## 2 20_Tag40118_Z-175_10 2020-05-23 01:11:00 16.91178928 42.79809711 1882.611772
## y x.se y.se u v
## 1 5248.851500 9.999990762e-06 9.999951414e-06 2.630553167e-12 2.092932393e-12
## 2 5252.251028 4.504251162e+00 4.504240895e+00 8.475094487e+00 6.806617985e+00
## u.se v.se s s.se
## 1 0.000010000 0.00001000 1.856746329e-314 NA
## 2 9.018512652 9.01850149 1.085794797e+01 NA
## id date lc lon lat smaj smin eor
## 1 20_Tag40118_Z-175_10 2020-05-23 00:41:02 G 16.873765 42.775604 NA NA NA
## 2 20_Tag40118_Z-175_10 2020-05-23 02:00:55 G 16.976549 42.837699 NA NA NA
## obs.type keep x y emf.x emf.y
## 1 GPS TRUE 1878.378928 5248.851500 0.1 0.1
## 2 GPS TRUE 1889.820790 5258.239344 0.1 0.1
## dataset_id scientific_name common_name site_name colony_name
## 1 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## 2 tbc Puffinus yelkouan Yelkouan Shearwater Lastovo SPA Z
## lat_colony lon_colony device ID track_id
## 1 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## 2 tbc tbc GPS 20_Tag40118_Z-175 20_Tag40118_Z-175
## original_track_id age sex breed_stage breed_status date_gmt
## 1 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## 2 20_Tag40118_Z-175 adult unknown chick-rearing breeding 2020-05-23
## time_gmt argos_quality equinox dttm bird_id_num Longitude
## 1 00:41:02 NA NA 2020-05-23 00:41:02 27 16.873765
## 2 02:00:55 NA NA 2020-05-23 02:00:55 27 16.976549
## Latitude nlocs track_segment track_colour DateTime
## 1 42.775604 1 track.start #66c2a5 2020-05-23 00:41:02
## 2 42.837699 2 track.start #66c2a5 2020-05-23 02:00:55
## tripID X Y Returns StartsOut ColDist
## 1 20_Tag40118_Z-175_10 16.873765 42.775604 Yes 4236.43456
## 2 20_Tag40118_Z-175_10 16.976549 42.837699 Yes 10399.61143
## dataGroup.Longitude dataGroup.Latitude optional
## 1 16.873765 42.775604 TRUE
## 2 16.976549 42.837699 TRUE
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 5: Plot the different tabular ouputs after fitting the model"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## plot the FITTED values over original data (i.e. locations used for fitting the model)
map %>% addCircleMarkers(data = floc.fitted,
#label = bird_track_gaps$nlocs,
radius = 3,
fillColor = "lightgreen",
fillOpacity = 0.5, stroke = F) %>%
addLegend(colors = "lightgreen",
labels = "fitted values")
## plot the PREDICTED values over original data (i.e. locations predcited from the model)
map %>% addCircleMarkers(data = floc.predicted,
#label = bird_track_gaps$nlocs,
radius = 3,
fillColor = "cyan",
fillOpacity = 0.5, stroke = F) %>%
addLegend(colors = "cyan",
labels = "predicted values")
## plot the REMOVED values over original data (i.e. locations that were removed from the prefiltering step)
map %>% addCircleMarkers(data = subset(floc.data, floc.data$keep == F),
#label = bird_track_gaps$nlocs,
radius = 3,
fillColor = "red",
fillOpacity = 0.5, stroke = F) %>%
addLegend(colors = "red",
labels = "removed values")
## plot the PREDICTED AND REMOVED values over original data (i.e. locations that were removed from the prefiltering step)
map %>% addCircleMarkers(data = floc.predicted,
#label = bird_track_gaps$nlocs,
radius = 3,
fillColor = "cyan",
fillOpacity = 0.5, stroke = F) %>%
addCircleMarkers(data = subset(floc.data, floc.data$keep == F),
#label = bird_track_gaps$nlocs,
radius = 5,
fillColor = "red",
fillOpacity = 0.5, stroke = F)
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 6: Visualising a model fit"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## null device
## 1
plot(fit, what = "fitted", type = 1, pages = 1)
# plot time-series of the predcited values
dev.off()
## null device
## 1
## null device
## 1
plot(fit, what = "predicted", type = 2, pages = 1,
## 95 % confidence ellipses (orange-filled ellipses) around the predicted
## values are also displayed, but can be faded away by choosing a low alpha value
alpha = 0.05,
## Observations that failed the prefilter stage are displayed (black x’s)
## by default but can be turned off with the argument outlier = FALSE)
outlier = T)
# plot fitted values as a 2-d track
dev.off()
## null device
## 1
plot(fit, what = "predicted", type = 2, pages = 1,
## 95 % confidence ellipses (orange-filled ellipses) around the predicted
## values are also displayed, but can be faded away by choosing a low alpha value
alpha = 0.00,
## Observations that failed the prefilter stage are displayed (black x’s)
## by default but can be turned off with the argument outlier = FALSE)
outlier = T)
"CONSIDER: How can we help user to decide whether their data is of high enough
quality or not for a track2KBA styled analysis? Perhaps the outputs from
grab(fit, what = predicted) can be of help? Here, see an indication of standard
errors around predicted locations via (x.se, y.se in km)"
## [1] "CONSIDER: How can we help user to decide whether their data is of high enough\nquality or not for a track2KBA styled analysis? Perhaps the outputs from \ngrab(fit, what = predicted) can be of help? Here, see an indication of standard \nerrors around predicted locations via (x.se, y.se in km)"
## null device
## 1
## null device
## 1
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 7: Further assessment of model fit"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## SEE: https://ianjonsen.github.io/aniMotum/articles/SSM_validation.html
"Does this assessment take into account all tracks simultanesouly? Or does it only
assess each track individually? What are the implications for this assessment in
the context of track2KBA? Not sure..."
## [1] "Does this assessment take into account all tracks simultanesouly? Or does it only\nassess each track individually? What are the implications for this assessment in\nthe context of track2KBA? Not sure..."
# use patchwork package to arrange plot.osar options
#library(patchwork)
# calculate & plot residuals
"NOTE: Computationally intensive! Takes time!!"
## [1] "NOTE: Computationally intensive! Takes time!!"
#res.rw <- osar(fit)
#(plot(res.rw, type = "ts") | plot(res.rw, type = "qq")) /
# (plot(res.rw, type = "acf") | plot_spacer())
"~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 8: Assess potential behaviours along track: Move_persistence_models"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## SEE: https://ianjonsen.github.io/aniMotum/articles/Move_persistence_models.html
## NOTE: You can fit this model in two ways
## SEE: Alternate script: tracking_CleanAndPrepareData2_AllTracks_aniMotumAllSteps
"~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 9: Reroute tracks that went overland back via the sea"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## NOTE: This will reroute the point locations only! So if you have a very detailed
## coastline, then it may appear the animals still move over land when plotting lines
## between points. The success of the analysis is also dependent on the underlying
## basemap used. The natural earth map (used by default) is good, but not very finely
## detailed. i.e. resolution could be higher
## install packages
#install.packages("pathroutr", repos = "https://jmlondon.r-universe.dev")
library(pathroutr) # for rerouting tracks
#install.packages("devtools")
#devtools::install_github("ropensci/rnaturalearthhires")
library(rnaturalearthhires) # for higher resolution natural earth map
## reroute the track using the predicted values of the previously fitted model
fit.reroute <- route_path(fit,
what = "predicted",
map_scale = 10,
dist = 10000,
append = T)
## data.frame of rerouted values
## NOTE: Some of these locations may not be ecologically realistic anymore
## i.e. if you were to recalculate travel speeds, they may be unrealistic
## must consider trade-off of approach accordingly
floc.predicted.reroute <- grab(fit.reroute, what = "rerouted")
## review data
head(data.frame(floc.predicted),2)
## id date lon lat x
## 1 20_Tag40118_Z-175_10 2020-05-23 00:41:00 16.87376500 42.77560400 1878.378928
## 2 20_Tag40118_Z-175_10 2020-05-23 01:11:00 16.91178928 42.79809711 1882.611772
## y x.se y.se u v
## 1 5248.851500 9.999990762e-06 9.999951414e-06 2.630553167e-12 2.092932393e-12
## 2 5252.251028 4.504251162e+00 4.504240895e+00 8.475094487e+00 6.806617985e+00
## u.se v.se s s.se
## 1 0.000010000 0.00001000 1.856746329e-314 NA
## 2 9.018512652 9.01850149 1.085794797e+01 NA
## id date lon lat x
## 1 20_Tag40118_Z-175_10 2020-05-23 01:11:00 16.91178928 42.79809711 1882.611772
## 2 20_Tag40118_Z-175_10 2020-05-23 01:41:00 16.95701156 42.82535314 1887.645892
## y x.se y.se
## 1 5252.251028 4.504251162 4.504240895
## 2 5256.372077 3.176431626 3.176422433
## plot original vs predicted vs re-routed
map %>%
## Predicted
addCircleMarkers(data = floc.predicted,
#label = bird_track$nlocs,
radius = 5,
fillColor = "green",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between predicted points
addPolylines(lng = floc.predicted$lon,
lat = floc.predicted$lat, weight = 1,
color = "green") %>%
## RE-ROUTED
addCircleMarkers(data = floc.predicted.reroute,
#label = bird_track$nlocs,
radius = 3,
fillColor = "red",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between re-routed points
addPolylines(lng = floc.predicted.reroute$lon,
lat = floc.predicted.reroute$lat, weight = 1,
color = "red")
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 10: Reroute tracks that went overland back via the sea using pathroutr package"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## SEE: https://rdrr.io/github/jmlondon/pathroutr/f/vignettes/reroute_demo.Rmd
## Consider the tutorial for pathroutr
## NOTE: This is very computationally expensive when you have many data points
## and high resolution coastline data. Therefore, it may be worth subsetting
## parts of the track that go over land and trying to reroute these parts only.
## Then you could merge these parts of the track back onto the remainder of the track
"~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 11: Simulate animal tracks"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## NOTE: This step is used more for habitat modelling / SDMs.
## Step not required for track2KBA
st <- sim_fit(fit, what="predicted", reps=5,
## cpf: is the animal exhibiting central place foraging behaviour?
cpf=T)
dev.off()
## null device
## 1
#plot(st)
"NOTE: Can also reroute these simulated tracks again as above.
Will need to consider application of this step."
## [1] "NOTE: Can also reroute these simulated tracks again as above.\nWill need to consider application of this step."
43.10 Compare different interplation methods
Now that you have applied the different inteprolation methods, you can compare the outputs.
Compare the outputs via visual inspection.
[Consider discussions about ways to support comparisons]
## plot original vs predicted from aniMotum vs re-routed from aniMotum vs speedfilter & linear interpolation
map %>%
## Predicted
addCircleMarkers(data = floc.predicted,
#label = bird_track$nlocs,
radius = 5,
fillColor = "green",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between predicted points
addPolylines(lng = floc.predicted$lon,
lat = floc.predicted$lat, weight = 1,
color = "green") %>%
## RE-ROUTED
addCircleMarkers(data = floc.predicted.reroute,
#label = bird_track$nlocs,
radius = 3,
fillColor = "red",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between re-routed points
addPolylines(lng = floc.predicted.reroute$lon,
lat = floc.predicted.reroute$lat, weight = 1,
color = "red") %>%
## Speed Filtered and Linear interpolated
addCircleMarkers(data = trip_interp,
#label = bird_track$nlocs,
radius = 3,
fillColor = "cyan",
fillOpacity = 0.5, stroke = F) %>%
## plot lines between Speed Filtered and Linear interpolated points
addPolylines(lng = trip_interp$Longitude,
lat = trip_interp$Latitude, weight = 1,
color = "cyan")
43.11 Review comparison
You can see from plot above that the “advanced” interpolation method of CRAWL via aniMotum
creates some additional loops on the tracking data. I.e it appears that the animal sort of shoots past some points and then returns back.
Either this tutorial is applying the aniMotum protocol incorrectly to the data, OR:
It’s likely that the algorithm underpinning something like CRAWL is more suited to animal tracking data for diving marine predators that move much more slowly.
Future examples should consider comparisons with tracking data for diving marine predators.
43.12 Interpolation: all data
[Will also need to find appropriate way to bind metadata back to individual trips]
Now that you have compared interpolation methods, you will want to apply the interpolation to all trips from the tracked animals.
43.12.1 Linear interpolation: all animals
# ## total number of trips
# length(unique(tracks$tripID))
#
# ## create data frame and remove trips with <5 locations; as required for track2KBA analysis
# trips_to_keep <- data.frame(tracks) %>%
# group_by(tripID) %>%
# summarise(triplocs = n()) %>%
# dplyr::filter(triplocs > 5)
#
# ##
# tracks_df <- data.frame(tracks) %>%
# dplyr::filter(tripID %in% trips_to_keep$tripID)
#
# ##
# length(unique(tracks_df$tripID))
#
# ## start blank df
# tracks_interp_df <- data.frame()
#
# for(i in 1:length(unique(tracks_df$tripID))){
# temp <- tracks_df %>% dplyr::filter(tripID == unique(tracks_df$tripID)[i])
#
# ## remove any erroneous locations due to speed use the McConnel Speed Filter
# ##from the trip package
# trip_obj <- temp %>%
# #group_by(tripID) %>%
# dplyr::select(x = X,
# y = Y,
# DateTime,
# everything()) %>%
# trip()
#
# ## McConnel Speedilter -----
# ## apply speedfilter and creat data frame
# trip_obj$Filter <- speedfilter(trip_obj, max.speed = 100) # speed in km/h
# trip_obj <- data.frame(trip_obj)
# head(trip_obj,2)
#
# ## How many locations were removed with speed filter?
# nrow(subset(trip_obj, trip_obj$Filter == F))
#
# ## Keep only filtered coordinates - after checking dimensions of other outputs again
# trip_obj <- subset(trip_obj,trip_obj$Filter==TRUE)
#
# ## Linear interpolation -----
# ## Apply linear interpolation step to speed filtered only data
#
# ## create ltraj object
# trip_lt <- as.ltraj(xy = bind_cols(x = trip_obj$x,
# y = trip_obj$y),
# date = trip_obj$DateTime,
# id = trip_obj$tripID)
#
# ## Linearly interpolate/re-sample tracks every 30 minutes (specified in seconds)
# trip_interp <- redisltraj(trip_lt, 1800, type="time")
# head(trip_interp)
#
# ## convert back into format for track2KBA - dataframe for now
# trip_interp <- ld(trip_interp) %>%
# dplyr::mutate(Longitude = x,
# Latitude = y)
#
# ## bind back onto dataframe
# tracks_interp_df <- rbind(tracks_interp_df, trip_interp)
#
# ## remove temporary items before next loop iteration
# rm(temp,trip_lt,trip_obj)
#
# ##
# print(i)
#
# }
#
# ## review it worked by checking total number of unique trips and comparing to original
# length(unique(tracks_df$tripID))
# length(unique(tracks_interp_df$id))
43.12.2 Advanced interpolation: all animals
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## aniMotum filter: All trips ----
## Bulk filter individual trips from all birds ----
"May need to consider a way of bulk checking quality of data."
## [1] "May need to consider a way of bulk checking quality of data."
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
## [1] "STEP 1: Format the data"
## [1] "~~~~~~~~~~~~~~~~~~~~~~~"
# all_track_am <- data.frame(tracks) %>% mutate(lc = "G") %>%
# dplyr::select(id = "tripID",
# date = "dttm",
# lc,
# lon = "Longitude",
# lat = "Latitude")
#
# ## remove trips with <5 locations; as required for track2KBA analysis
# trips_to_keep <- all_track_am %>%
# group_by(id) %>%
# summarise(triplocs = n()) %>%
# dplyr::filter(triplocs > 5)
#
# ## filter out the tracks
# all_track_am <- all_track_am %>% dplyr::filter(id %in% trips_to_keep$id)
#
#
# ##
# head(all_track_am,2)
# length(unique(all_track_am$id))
#
#
# "~~~~~~~~~~~~~~~~~~~~~~~"
# "STEP 2: Fit the model"
# "~~~~~~~~~~~~~~~~~~~~~~~"
#
# ## fit the model to all data
# fit_alltrack <- fit_ssm(all_track_am,
# ## specify what kind of model you want to fit. See details about different model types in paper.
# model = "crw",
# ## specify the speed at which data points could be considered outlier points (in m/s)
# vmax = 27,
# ## time.step in hours - specify time.step of new values to be predicted (interpolation)
# time.step = 0.5)
#
# "NOTE: Depending on how you prefilter your data before running fit_ssm, you may
# want to consider changing some of the function parameters. E.g. you might indicate
# fit.to.subset = F, if you have filtered your data already and are sure all your
# locations are true locations."
#
#
# "~~~~~~~~~~~~~~~~~~~~~~~"
# "STEP 3: Review the model fit"
# "~~~~~~~~~~~~~~~~~~~~~~~"
#
# ## review the model summary
# ## See: https://ianjonsen.github.io/aniMotum/articles/Overview.html
# "Check that converged and phHess were True. NOTE: I'm not sure what it means if they are false"
# fit_alltrack
# fit_alltrack %>% dplyr::filter(converged == F)
# fit_alltrack %>% dplyr::filter(pdHess == F)
# "Review overall summaries and SSM details for each individual. Again, not entirely sure what all the important bits are"
# summary(fit_alltrack)
#
# "~~~~~~~~~~~~~~~~~~~~~~~"
# "STEP 9: Reroute tracks that went overland back via the sea"
# "~~~~~~~~~~~~~~~~~~~~~~~"
#
# ## NOTE: This will reroute the point locations only! So if you have a very detailed
# ## coastline, then it may appear the animals still move over land when plotting lines
# ## between points. The success of the analysis is also dependent on the underlying
# ## basemap used. The natural earth map (used by default) is good, but not very finely
# ## detailed. i.e. resolution could be higher
#
# ## reroute the track using the predicted values of the previously fitted model
# fit.reroute.all <- route_path(fit_alltrack,
# what = "predicted",
# map_scale = 10,
# dist = 10000,
# append = T)
#
# ## data.frame of rerouted values
# ## NOTE: Some of these locations may not be ecologically realistic anymore
# ## i.e. if you were to recalculate travel speeds, they may be unrealistic
# ## must consider trade-off of approach accordingly
# floc.predicted.reroute <- grab(fit.reroute, what = "rerouted")
#
# ## review data
# head(data.frame(floc.predicted),2)
# head(data.frame(floc.predicted.reroute),2)