calbertsen / argosTrack

R package for fitting animal movement models to Argos (or other types of location) data
12 stars 7 forks source link

Predicting unkonwn locations at known times #6

Closed jmhatch closed 1 year ago

jmhatch commented 1 year ago

Hi Dr. Albertsen,

I was wondering how to predict unknown locations from a fitted movement model using the state-space approach of {argosTrack} in a manner similar to Johnson et al. (2011) and Fleming et al. (2016). My first guess is that you could interleave times that you want to predict locations at (like every 6 hours) with the observed data and then tell {argosTrack} not to include them in the measurement likelihood. Although, this introduces more estimated random effects (resulting in more random effects than observed data, so perhaps not a good approach). And currently doesn't work (probably for good reason; see code below).

I'm most interested in the CTCRW movement model, and I was wondering if it would be possible to use the kriging approach from the Fleming et al. (2016) paper to predict unknown locations from a fitted movement model using {argosTrack}. Seems possible, just not sure how to start off. The kriging approach just requires a mean and autocorrelation function to be specified, and some assumptions about normality (from what I can tell). From here, we see that the covariance for locations ($x$) at times $t$ and $t'$ of the CTCRW movement model is defined as:

$$ \text{Cov}[x(t),x(t')] = \frac{\sigma^2}{2a^3}\left(2e^{-at}-e^{-a(t+t')}-e^{-a|t'-t|}+2e^{-at'}+2\min(t,t')-2\right). $$

where the CTCRW model is derived from the following sdes,

$$ dx_t = v_tdt $$

with velocity ($v_t$) as an OU process

$$ dv_t = a(b-v_t)dt + \sigma dW_t. $$

Although, they derive the $\text{Cov}$ assuming $\mathbf{b} = \mathbf{0}$ (so that may throw a wrench in things, if it's of interest to also estimate $\mathbf{b}$). Just wanted to get your thoughts and thank you for the great R pkg! I know there is {ctmm} and {crawl}, but I like the flexibility of using TMB on the backend.

library(argosTrack)
library(dplyr)
library(magrittr)

## example data from {argosTrack}
dat = subadult_ringed_seal %>%
  mutate(date = as.POSIXct(date))

## remove duplicated timestamps
dat %<>% arrange(date) %>% 
  dplyr::filter(duplicated(date) == FALSE)

## datetimes to predict unknown locations from the fitted movement model
preds = tibble(include = FALSE, 
               date = seq(min(dat$date), max(dat$date), by = '6 hours'))

## merge predicted times with the "observed" data
ex_dat = dplyr::bind_rows(dat, preds) %>% 
  arrange(date) %>%
  mutate(include = ifelse(is.na(include), TRUE, include))

## remove duplicated dates introduced by rbinding preds (keep observed, remove pred)
ex_dat %<>% arrange(date, -include) %>%
  dplyr::filter(duplicated(date) == FALSE)

## set up Observation obj.
obs = Observation(lat = ex_dat$lat,
                  lon = ex_dat$lon,
                  dates = ex_dat$dates,
                  locationclass = ex_dat$lc,
                  include = ex_dat$include
                  )

Error in .Object$initialize(...) : 
  lon can not have NULL, NA, or NaN  elements.
calbertsen commented 1 year ago

It is possible to include time points without observations, but it has to be done in the movement model part instead of the observation part:

## Loading data
d <- subadult_ringed_seal
d$date <- as.POSIXct(d$date)

## Observation part needs observed locations
obs <- Observation(lon = d$lon,
                   lat = d$lat,
                   dates = as.POSIXct(d$date),
                   locationclass = d$lc
                   )
obs

## Measurement model
meas <- Measurement(model="n")
meas

## A vector of all the dates to include
allDates <- sort(unique(c(seq(min(d$date), max(d$date), by = '6 hours'),
                   as.POSIXct(d$date))))
## Movement model will now have time points every 6h and where there are observations
mov <- CTCRW(allDates)

## Combine parts to 'Animal'
anim <- Animal(obs,mov,meas, "Subadult ringed seal")

## Fit track
fitTrack(anim)

## Plot of result
plot(anim)

## Extract fitted track with getTrack. Includes all estimated time points. Observation is NA for some.
head(getTrack(anim),10)
jmhatch commented 1 year ago

Thanks! I've noticed that as the number of latent parameters grows (by making the time step finer in allDates), the model starts to push the $\gamma$ parameters to 0. The other parameters of the CTCRW model also shift some, although given the ranges maybe this can be chocked up to numerical issues.

image

I also noticed none of the models converged, stating "false convergence (8)", with large max gradient values. I may try to see if I can get the kriging approach to work (as it avoids having to estimate additional random effects, if I'm understanding things correctly - which there is a good chance I'm not). Thanks again! Really useful R pkg for animal movement modeling.