Purpose

Demonstrate how to build animated tracking maps using tracking data in Movebank, environmental covariates in track and raster annotations from EnvDATA, and the moveVis package written by Jakob Schwalb-Willmann. Subsequent examples become more complete and cover more complicated situations.

Notes: * Consider exploring tracking data in Movebank, DynamoVis (https://doi.org/10.13020/D6PH49) and/or Google Maps first to evaluate datasets you’re not yet familiar with and plan out animations. * See more about the moveVis package at http://movevis.org.

Load libraries

library(ggplot2)
library(moveVis)
library(move)
library(magrittr)
library(raster)
options(max.print=100)
options(width=95)

Prepare the tracking data.

Load the Svalbard geese dataset (Griffin, 2014, https://doi.org/10.5441/001/1.5k6b1364).

geese.move <- move("data/annotations/Svalbard geese 1k 16d NDVI-3281758398705165226/Svalbard geese 1k 16d NDVI-3281758398705165226.csv")
geese.move
## class       : MoveStack 
## features    : 24488 
## extent      : -4.029, 22.421, 54.15566, 78.71467  (xmin, xmax, ymin, ymax)
## coord. ref. : +proj=longlat +ellps=WGS84 +datum=WGS84 +towgs84=0,0,0 
## variables   : 6
## names       :  event.id,           timestamp,  comments, height.raw, MODIS.Land.Vegetation.Indices.1km.16d.Aqua.NDVI, MODIS.Land.Vegetation.Indices.1km.16d.Terra.NDVI 
## min values  : 369331563, 2006-04-05 07:00:00, 170563-07,       -0.1,                                    1.000006e-02,                                     1.000000e-02 
## max values  : 369356755, 2011-06-18 17:00:00,  86828-09,       NULL,                                   -9.997746e-03,                                    -9.998666e-02 
## timestamps  : 2006-04-05 07:00:00 ... 2011-06-18 17:00:00 Time difference of 1900 days  (start ... end, duration) 
## sensors     : gps 
## indiv. data : visible, algorithm.marked.outlier, sensor.type, individual.taxon.canonical.name, tag.local.identifier, individual.local.identifier, study.name 
## min ID Data : true, NA, gps, Branta leucopsis,  33102, X170563, Migration timing in barnacle geese (Svalbard) (data from Kölzsch et al. and Shariatinajafabadi et al. 2014) 
## max ID Data : true, NA, gps, Branta leucopsis, 186827,  X86828, Migration timing in barnacle geese (Svalbard) (data from Kölzsch et al. and Shariatinajafabadi et al. 2014) 
## individuals : X33102, X33103, X33104, X33145, X33953, X33954, X64685, X64687, X70564, X70565, X70566, X70567, X70568, X70618, X70619 
## study name  : Migration timing in barnacle geese (Svalbard) (data from Kölzsch et al. and Shariatinajafabadi et al. 2014) 
## date created: 2018-09-12 16:39:55

As shown in “timestamps” this study covers 5 years (4/5/2006 to 6/18/2011, 1900 days). Before building animations, check the spread of the data over time.

geese.df <- as.data.frame(geese.move)
ggplot() +
  geom_point(data = geese.df, aes(x = timestamp, y = individual.local.identifier)) +
  theme(legend.position = "none") # hide legend

Let’s reduce it to the migration with the largest number of birds (spring 2007).

geese.s07 <- subset(geese.move, timestamp >= as.POSIXct('2007-04-01 00:00:00.000') 
                    & timestamp <= as.POSIXct('2007-06-15 00:00:00.000'))

Make frames of tracking data for animation.

Evaluate tracking data for sampling rates if unknown. Use this information to help decide the temporal resolution at which to align the data for the animation.

unique(timestamps(geese.s07))
##   [1] "2007-04-01 10:00:00 UTC" "2007-04-01 12:00:00 UTC" "2007-04-01 14:00:00 UTC"
##   [4] "2007-04-01 16:00:00 UTC" "2007-04-01 18:00:00 UTC" "2007-04-02 04:00:00 UTC"
##   [7] "2007-04-02 06:00:00 UTC" "2007-04-02 08:00:00 UTC" "2007-04-02 10:00:00 UTC"
##  [10] "2007-04-02 12:00:00 UTC" "2007-04-02 14:00:00 UTC" "2007-04-02 16:00:00 UTC"
##  [13] "2007-04-02 18:00:00 UTC" "2007-04-02 20:00:00 UTC" "2007-04-03 06:00:00 UTC"
##  [16] "2007-04-03 08:00:00 UTC" "2007-04-03 10:00:00 UTC" "2007-04-03 12:00:00 UTC"
##  [19] "2007-04-03 14:00:00 UTC" "2007-04-03 16:00:00 UTC" "2007-04-03 18:00:00 UTC"
##  [22] "2007-04-04 04:00:00 UTC" "2007-04-04 06:00:00 UTC" "2007-04-04 08:00:00 UTC"
##  [25] "2007-04-04 10:00:00 UTC" "2007-04-04 12:00:00 UTC" "2007-04-04 14:00:00 UTC"
##  [28] "2007-04-04 16:00:00 UTC" "2007-04-04 18:00:00 UTC" "2007-04-04 20:00:00 UTC"
##  [31] "2007-04-05 04:00:00 UTC" "2007-04-05 06:00:00 UTC" "2007-04-05 08:00:00 UTC"
##  [34] "2007-04-05 16:00:00 UTC" "2007-04-05 18:00:00 UTC" "2007-04-05 20:00:00 UTC"
##  [37] "2007-04-06 04:00:00 UTC" "2007-04-06 06:00:00 UTC" "2007-04-06 08:00:00 UTC"
##  [40] "2007-04-06 10:00:00 UTC" "2007-04-06 12:00:00 UTC" "2007-04-06 14:00:00 UTC"
##  [43] "2007-04-06 16:00:00 UTC" "2007-04-06 18:00:00 UTC" "2007-04-07 04:00:00 UTC"
##  [46] "2007-04-07 06:00:00 UTC" "2007-04-07 08:00:00 UTC" "2007-04-07 10:00:00 UTC"
##  [49] "2007-04-07 12:00:00 UTC" "2007-04-07 14:00:00 UTC" "2007-04-08 04:00:00 UTC"
##  [52] "2007-04-08 06:00:00 UTC" "2007-04-08 08:00:00 UTC" "2007-04-08 10:00:00 UTC"
##  [55] "2007-04-08 12:00:00 UTC" "2007-04-08 14:00:00 UTC" "2007-04-08 16:00:00 UTC"
##  [58] "2007-04-08 18:00:00 UTC" "2007-04-09 10:00:00 UTC" "2007-04-09 12:00:00 UTC"
##  [61] "2007-04-09 14:00:00 UTC" "2007-04-09 16:00:00 UTC" "2007-04-09 18:00:00 UTC"
##  [64] "2007-04-09 20:00:00 UTC" "2007-04-10 06:00:00 UTC" "2007-04-10 08:00:00 UTC"
##  [67] "2007-04-10 10:00:00 UTC" "2007-04-10 12:00:00 UTC" "2007-04-10 14:00:00 UTC"
##  [70] "2007-04-10 16:00:00 UTC" "2007-04-10 18:00:00 UTC" "2007-04-10 20:00:00 UTC"
##  [73] "2007-04-11 10:00:00 UTC" "2007-04-11 12:00:00 UTC" "2007-04-11 14:00:00 UTC"
##  [76] "2007-04-11 16:00:00 UTC" "2007-04-11 18:00:00 UTC" "2007-04-11 20:00:00 UTC"
##  [79] "2007-04-12 04:00:00 UTC" "2007-04-12 06:00:00 UTC" "2007-04-12 08:00:00 UTC"
##  [82] "2007-04-12 10:00:00 UTC" "2007-04-12 12:00:00 UTC" "2007-04-12 14:00:00 UTC"
##  [85] "2007-04-12 16:00:00 UTC" "2007-04-12 18:00:00 UTC" "2007-04-12 20:00:00 UTC"
##  [88] "2007-04-14 04:00:00 UTC" "2007-04-14 06:00:00 UTC" "2007-04-14 08:00:00 UTC"
##  [91] "2007-04-14 16:00:00 UTC" "2007-04-14 18:00:00 UTC" "2007-04-14 20:00:00 UTC"
##  [94] "2007-04-15 10:00:00 UTC" "2007-04-15 12:00:00 UTC" "2007-04-15 14:00:00 UTC"
##  [97] "2007-04-15 16:00:00 UTC" "2007-04-15 18:00:00 UTC" "2007-04-15 20:00:00 UTC"
## [100] "2007-04-16 04:00:00 UTC"
##  [ reached 'max' / getOption("max.print") -- omitted 1040 entries ]
timeLag(geese.s07, unit = "hours")
## $X64687
##   [1]  2  2  2  2 10  2  2  2  2  2  2  2  2 10  2  2  2  2  2  2 10  2  2  2  2  2  2  2  2  8
##  [31]  2  2  8  2  2  8  2  2  2  2  2  2  2 10  2  2  2  2  2 14  2  2  2  2  2  2  2 16  2  2
##  [61]  2  2  2 10  2  2  2  2  2  2  2 14  2  2  2  2  2  8  2  2  2  2  2  2  2  2 32  2  2  8
##  [91]  2  2 14  2  2  2  2  2  8  2
##  [ reached getOption("max.print") -- omitted 333 entries ]
## 
## $X70564
##   [1]  1  1  1  1  1  3  2  8  2  2  2  2  2  2  2 20  2  2 14  2  2  2  2  2  2  8  2  8  2  2
##  [31]  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2 44  2  2  2  2  2  2 10  2  2  2  2  2  2  2
##  [61]  8  2  2  2  2  2  2  2 14  2  2  8  8  2  2  2  2  2  2  2 14  2  2  2  2  2  2  8  2  2
##  [91]  2  2  2  2  2 14  2  2  2  2
##  [ reached getOption("max.print") -- omitted 405 entries ]
## 
## $X70565
##   [1]  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2  2 14 30  2  2 10  2  2  2  2  2  2  2 10  2
##  [31]  2  2  2  2  2  2 10  2  2  2  2 16  2  8  2 12  2  2  2  2  2  2  2  8  2  2  8  2 16  2
##  [61]  2  2  2  2 10  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2  2 10  2  2  2  2  2  2  2 10
##  [91]  2  2  2  2  2  2  2 10  2  2
##  [ reached getOption("max.print") -- omitted 471 entries ]
## 
## $X70566
##   [1]  2  2 68  2  2  8  2  2  2  2  2  2  2  2  8  2  2 44  2  2  8  2  2  8  2  2  2  2  2  2
##  [31]  2  2 10  2  2  2  2  2  2  2 14  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2
##  [61]  2  2  2  2  8  2  2  2  2  2 14  2  2 26  2  2  2  2  2  8  2  4  2  2  2  2  2 10  2  8
##  [91]  2  2 32  2  2 20  2 22  2  2
##  [ reached getOption("max.print") -- omitted 413 entries ]
## 
## $X70567
##   [1]  2  2  2  2 40  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  2  2 26  2  2 44  2  2  2  2
##  [31] 10  2  2  2  2  2 50  2 16  2  2  2  2  2  8  2  2  2  2  2  2  2  2 10  2 26  2  2 14  2
##  [61]  2  2  2  2  2  2  2 14  2  2  2  2  2  8  2  2 56  2  2 32  2  2 50  2  2  2  2  2 20  2
##  [91]  2  8  2  2  2  2  2  2  2  2
##  [ reached getOption("max.print") -- omitted 410 entries ]
## 
## $X70568
##   [1]  2  2  2  2  2 14  2  2  2  2  2  8  2  2  2  2  2  2  2  2 62  2  2  2  2  2  8  2  2  2
##  [31]  2  2  2 12  2  2 20  2  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2  2
##  [61]  2  2  2  8  2  2 26  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  6  2  2  2  2  2 20  2
##  [91]  2  8  2  2 50  2  2 74  2  2
##  [ reached getOption("max.print") -- omitted 215 entries ]
## 
## $X70618
##   [1]  2  2  2  2  2  2  2  2  8  2  2 20  2  2  2  2  2 14  2  2  2  2  2  2  2  2  8  2  2  2
##  [31]  2  2  2  2  2  8  2  2 20  2  2 26  2  2  2  2  2  8  2  2  2  2  2  2  2 16  2  2  2  2
##  [61]  2 10  2  8  2  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2  2 14  2  2  2  2  2 20  2  2
##  [91]  2  2  2  8  2  2  2  2  2  2
##  [ reached getOption("max.print") -- omitted 524 entries ]
## 
## $X70619
##   [1]  2  2  2  2  2  2  2 10  2  2  2  2  2 14  2  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2
##  [31]  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  2  2 68  2  2  2  2  2  2  2
##  [61]  2 10  2 32  2  2  8  2  2  2  2  2  2  2  2  8  2  2  2  2  2  2  2  2  8  2  2  8  2  2
##  [91]  8  2  2  2  2  2  2  2  2 20
##  [ reached getOption("max.print") -- omitted 471 entries ]
## 
## $X170563
##   [1]  4  1  1  2  2  8  2  2  2  8  2  8  2  2  2  2  2  2 20  2  2  2 10  2  2  2  2  2  2  2
##  [31] 10  2  2  2  2  2  2  2  2  8  2  2  2  2  2  2 26  2  8  2  2  2  2  2  2  2  2 10  2  2
##  [61]  2  2  2  2  2 10  2  2 32  2  8  2  2  2  8  2 22  2  8  8  2  2 38  2  2  8  2  8  2  2
##  [91]  2  2  2  2  2  2  8  2  2  2
##  [ reached getOption("max.print") -- omitted 439 entries ]

Align tracking data to uniform temporal resolution for interpretation by frames_spatial.

geese <- align_move(geese.s07, res = 12, unit = "hours", spaceMethod = "greatcircle")

Could use 2-hr resolution for a final product but 12-hr should speed up processing.

Create animation with static web basemap.

Create map frames for animation (see p.25 of MoveVis manual). Note that equidistant = TRUE does not mean that the map will be displayed in an equidistant projection (i.e. that preserves distances). Instead it causes frames_spatial to stretch the displayed area to an square extent. If equidistant = FALSE, the extent is displayed in the projection-native axis ratio.

frames <- frames_spatial(geese, map_service = "osm", map_type = "watercolor", 
                         equidistant = FALSE, path_legend = T, path_legend_title = "Geese", 
                         alpha = 0.5)
## Processing movement data...
## Retrieving and compositing basemap imagery...
## Assigning raster maps to frames...
## Creating frames...

Have a look at one of the frames.

frames[[100]]