rsMove - Remote Sensing for Movement Ecology

Ruben Remelgado


Why develop rsMove?

Remote sensing became a fundamental tool in the scope of movement ecology. It offers information on the spatial and temporal variability of the landscape and provides us the means to understand the impact of environmental change over animal behavior. However, linking remote sensing and animal movement can be troublesome due to the different spatial and temporal scales at which they are acquired. satellite images are collected with a relatively rough temporal and spatial resolution failing to reflect the landscape as perceived by an animal. However, when used adequately, remote sensing can help charactize the environmental factors that affect animal behavior. To achieve this, deciding which remote sensing data to use demands careful thinking In particular, two important questions should be considered: 1) Does the spatial and temporal resolution of a satellite preserve sufficient, non-replicated samples? 2) which environmental variables do I need to consider? rsMove addresses these questions by providing users with tools that help select adequate satellite data as well as suitable environmental variables. Moreover, this package offers tools that are sensitive to the technical constraints of remote sensing and introduce a remote sensing perspective into animal movement research 1.

Reference Data

rsMove was developed using movement data from one population of White Storks (ciconia ciconia) tracked with high-resolution GPS devices. The data was collected by the Max Planck Institute for Ornithology (MPIo) and it can be accessed here through MoveBank. Within rsMove, we provide data for a single individual divided into two datasets: one resampled to a lower temporal resolution showing the individuals migration to Africa (longMove) and one with the original temporal resolution showing movements within its nesting site (shortMove). The files are provided as SpatialPointsDataFrameobjects and can be accessed as seen below.


In addition, rsMove provides example remote sensing data. This consists of three Normalized Difference Vegetation Index (NDVI) images derived with Landsat surface reflectances. This data was acquired though the Earth Resources Observation and Science (EROS) Center Science Processing Architecture (ESPA), a service of the United States Geological Survey (USGS). Moreover, we provide land cover information (landCover) that overlaps with the shortMove dataset. This data was extracted from the European Urban Atlas. The code to access the remote sensing datasets is seen below.

# read remote sensing data
ndvi <- stack(list.files(system.file('extdata', '', package="rsMove"), 'ndvi.tif', full.names=TRUE))
landCover <- raster(system.file('extdata', 'landCover.tif', package="rsMove"))

# extract ndvi raster dates <- names(ndvi)
ndvi.dates <- as.Date(paste0(substr(, 2, 5), '-', substr(, 7, 8), '-', substr(, 10, 11)))

Input and output data

rsMove extends existing spatial analysis packages into movement ecology. Specifically, we focuses on the packages raster and sp as they are commonly used for image analysis thus facilitating the integration of rsMove in existing workflows. As a consequence, the input and processed movement data is often requested in SpatialPoints format while remote sensing data is provided in raster format. Moreover, rsMove provides a series of graphical outputs that accompany most of its functions. These plots are built with ggplot2 serving as a template that can be easily edited by the user.

Too much data, too little time. Where to start?

As GPS tracking technologies evolve, we are able to follow animal decision making at a finer temporal scale. Depending on the species and on the durability of the tracker, the observation periods can be extensive generating massive amounts of data to analyze. It is true that nowadays this issue has become smaller as the free access to cloud-computing platforms makes it easier to handle large volumes of data. However, when dealing with remote sensing, choosing the right combination of variables to explain a species behavior requires an iterative process of trial and error and a careful visual assessment. As a consequence, selecting representative test sites is essential.

hotMove() uses a relatively fast, pixel-based approach to address this issue. Given a pixel resolution, hotMove() translates a SpatialPoints object into unique pixels and evaluates their spatial connectivity on a regional scale. Then, the original samples are labeled based on the region of their corresponding pixels. Let’s consider the following example using the longMove dataset. As it extends over a large area and is provided with Geographic coordinates, we will use a pixel resolution of 0.1. This essentially means that samples which are within ~10 km of each other will be within the same pixel or within neighboring ones becoming part of the same region. Additionally, we will prompt the function to derive a shapefile with polygons for the sample regions by setting return.shp to TRUE.

sample.regions <- hotMove(xy=longMove, pixel.res=0.1, return.shp=TRUE)

The function identified 21 unique sample regions. The code below plots the region shapefile showing the relation between the original samples (in black) and the resulting regions (in red).

par(mar=c(4,4,0,4), xpd = NA, font.lab=2)
plot(longMove@coords[,1], longMove@coords[,2], pch=16, cex=0.5, xlab="Lon", ylab="Lat", cex.lab=1, cex.axis=1)
plot(sample.regions$polygons, col=rgb(1,0,0,0.3), add=TRUE)

Using the output of hotMove(), we can then use hotMoveStats() to deconstruct the temporal composition of the sample regions. For each sample region, hotMoveStats() identifies individual temporal segments - defined by sequences of consecutive days with movement data - and reports on the total number of segments, minimum and maximum segment lengths and the total time spent. Moreover, for each segment, the function reports on its region, the start and end dates and the total amount of days. Aside from this report, hotMoveStats() also provides the sample indices for each temporal segment allowing the user to identify the samples for relevant time periods. To run the function, as seen below, the user must provide hotMoveStats() with the sample indices acquired through hotMove() and the observation date of each sample. The summary report for each region can be seen below.

region.stats <- hotMoveStats($indices, obs.time=as.Date(longMove@data$timestamp))
Region ID Nr Samples Nr Individuals Min Time Average Time Max Time Total Time Nr Segments
1 28 NA 1 1 1 1 1
2 76 NA 1 1 1 2 2
3 77 NA 1 1 1 2 2
4 22 NA 1 1 1 1 1
5 1 NA 1 0 1 1 1

Aside from this information, hotMoveStats() also provides a plot showing the distribution of samples per sample region and the amount of time spent within them. Based on our example data, the plot shown below portraits an uneven distribution of samples with the region 21 accounting for ~3000 samples and ~80 days.

To make sense of these results, we can plot the polygons created by hotMove() and color them based on the output of hotMoveStats(). For this example, we used the total time spent per region. The plot shown below depicts the distribution of time per sample region. As a we can see, the region with most samples and time spent is clearly highlighted showing the location of the summering site of this White Stork.

The combination of hotMove()and hotMoveStats() provides us with a good understanding of the spatial and temporal distribution of the movement data allowing us to pinpoint relevant periods in space and time. Moreover, if the is specified within hotMoveStats(), the user will also receive information on how may individuals/species shared a temporal segment. If the user is interested in multi-species studies, this information can be useful to narrow down study sites and study periods over which remote sensing methods can be tested.

Which satellite to use? Choosing a Spatial and Temporal resolution

Due to the differences in spatial and temporal scales at which animal movement and remote sensing data are collected, matching these two data sources is not always easy. Issues such as the pseudo-replication of values in space and time are common leading to the presence of redundant information. As a result, it becomes crucial to understand how the choice in spatial and temporal scale affects movement data. To help researchers chose adequate satellite data we developed sMoveRes(), tMoveRes() and specVar().

sMoveRes() helps select an adequate spatial resolution. Given a spatial resolution and a SpatialPoints object, the function determines which pixels in a raster are sampled and evaluates their spatial connectivity as done by hotMove(). Let’s consider the following example. Taking the shortMove dataset, we will evaluate the suitability of the NDVI derived by commonly used satellite sensors: Sentinel-2 (10 m), Landsat (30 m) and MODIS (250 m). Below we can see the output which consisting of a data.frame and a plot depicting how the number of unique pixels and pixel regions changes with the change in spatial resolution. Moreover, the function reports on the pixel indices of each sample at each sample resolution showing which samples are grouped.

s.res <- sMoveRes(xy=shortMove, pixel.res=c(10, 30, 250))
n.pixels n.regions pixel.res
10 37 20 10
30 22 4 30
250 5 1 250

tMoveRes() does a similar analysis. However, this function uses a static spatial resolution and quantifies the number of samples and sample regions achievd with different temporal resolutions. Let’s consider longMove as it was collected over several days. As done with `hotMove(), we will set the spatial resolution to 0.01 (i.e. ~10 km). regarding the temporal resolution, let’s consider the example of MODIS for which we can acquire data every 1, 8 and 16 days. As we can see below, the output is very similar to the one produced by sMoveRes().

t.res <- tMoveRes(xy=longMove,$timestamp), time.res=c(1,8,16), pixel.res=0.01)
n.pixels n.regions resolution
682 527 527 1
292 212 212 8
252 182 182 16

In addition to these two tools, we developed specVar(). This function extends on sMoveRes() informing on how a spatial resolution reflects the complexity of the landscape. Let’s consider that sMoveRes() suggested a spatial resolution of 250 m is sufficient. Based on these results, the next question we should consider is: does this reflect the spatial complexity we are trying to capture? Within highly fragmented landscapes, where subtle transitions in land cover may be relevant for the species, this question becomes particular important. To test if a resolution of 250 m is adequate we will use the second layer of ndvi as it is the closest to the observation date of shortMove(). The image is shown below.

So what is specVar()doing? Well, first, the function will resample ndvi, which has a spatial resolution of 30 m, to 250 m. Then, the function will estimate the Mean Absolute Percent Error (MAPE) for each aggregated pixel estimated as

\(100/n \sum_{i=1}^n |\frac{O_{i} - F_{i}}{O_{i}}|\)

where 0i are the original values, Ai the aggregated value and ni the number of non-NA pixels in the original raster. This is a normalized measure allowing the user to establish comparisons with other variables and time-steps. As shown below, the function provides a raster of the MAPE and a histogram with the distribution of its values.

s.var <- specVar(img=ndvi[[2]], pixel.res=250)