Search code examples
loopsdebuggingeuclidean-distancecoordinate-systemsadehabitathr

Analysis of trajectories with ltraj returning odd outputs, why?


I am working with tracking data and stumbled upon the functions from the package "adehabitatLT", which I find quite handy for obtaining the descriptive parameters of my trajectories.

All strings of my code work properly, but unfortunately, I do not understand what's wrong to end up with unusual extremely low outputs (I am working with flying birds so I expect the results for velocity/speed and distance to be around 1-100 km/h and 2-3000 km max, respectively).

Here's a snippet and the structure of the relevant columns from my df called springsub:

> head(springsub)
  X            DateTime              id        lat        lon 
1 1 2022-05-03 19:39:00 N34246@096AFE12 45.7309083 13.3009833   
2 2 2022-05-03 21:39:00 N34246@096AFE12 46.3943317 14.9383667   
3 3 2022-05-03 23:39:00 N34246@096AFE12 47.3849317 16.5986833  
4 4 2022-05-04 01:39:00 N34246@096AFE12   48.44073 18.0876833 
5 5 2022-05-04 03:39:00 N34246@096AFE12   48.73939    18.5627 
6 6 2022-05-04 05:39:00 N34246@096AFE12  48.739305    18.5627  

> str(springsub)
'data.frame':   21053 obs. of  12 variables:
 $ X            : int  1 2 3 4 5 6 7 8 9 10 ...
 $ DateTime     : POSIXct, format: "2022-05-03 19:39:00" "2022-05-03 21:39:00" "2022-05-03 23:39:00" "2022-05-04 01:39:00" ...
 $ id           : chr  "N34246@096AFE12" "N34246@096AFE12" "N34246@096AFE12" "N34246@096AFE12" ...
 $ lat          : chr  "45.7309083" "46.3943317" "47.3849317" "48.44073" ...
 $ lon          : chr  "13.3009833" "14.9383667" "16.5986833" "18.0876833" ...

Here's my code so far:

library(adehabitatLT)
library(sp)
library(sf)

spring_sf <- st_as_sf(springsub, coords = c("lon", "lat"), crs = 4326)  

individual_ids <- unique(springsub$id) # get unique individual IDs 
ltraj_list <- list() # stores ltraj obj for each id

# loop plus some debugging that was needed for it to work properly
for (id in individual_ids) {
  cat("Processing individual:", id, "\n")
  individual_data <- spring_sf[spring_sf$id == id, ] 
  cat("Number of unique dates:", length(unique(individual_data$DateTime)), "\n") 
  if (anyDuplicated(individual_data$DateTime) > 0) {   
   individual_data$DateTime <- individual_data$DateTime + seq(0, length.out = nrow(individual_data), by = 1)
  } 

  individual_coords <- st_coordinates(individual_data) 
  tryCatch({    
individual_ltraj <- as.ltraj(individual_coords, date = individual_data$DateTime, id = individual_data$id, typeII = TRUE)
ltraj_list[[id]] <- individual_ltraj}, 
error = function(e) 
{
  cat("Error for individual:", id, "\n")
  print(e)
})
}

ld_results <- list()
for (i in seq_along(ltraj_list)) {
individual_ltraj <- ltraj_list[[i]]  
  ld_result <- ld(individual_ltraj)
  ld_results[[i]] <- ld_result
}
ltraj_metrics <- do.call(rbind, ld_results)

# adding relevant metrics 

# velocity
ltraj_metrics$velocity <- ltraj_metrics$dist / ltraj_metrics$dt

# euclidean distance and total distance
euclidean_distance <- aggregate(dist ~ id, data = ltraj_metrics, FUN = sum)
total_distance <- aggregate(dist ~ id, data = ltraj_metrics, FUN = sum)

# straightness
sum_R2n_per_ID <- aggregate(R2n ~ id, data = ltraj_metrics, FUN = sum)
sum_R2n_per_ID <- aggregate(R2n ~ id, data = ltraj_metrics, FUN = sum)
R2n_data <- merge(sum_R2n_per_ID, total_distance, by = "id")
R2n_data$straightness <- R2n_data$R2n / R2n_data$dist

# turning angle on x (abs.angle)
ltraj_metrics$turning_angle_x <- c(NA, diff(ltraj_metrics$abs.angle))
# turning angle on y (rel.angle)
ltraj_metrics$turning_angle_y <- c(NA, diff(ltraj_metrics$rel.angle))

And here's an example of the very odd outputs I get:

> head(ltraj_metrics)
         x        y                date        dx         dy         dist   dt       R2n  abs.angle   rel.angle              id
1 13.30098 45.73091 2022-05-03 19:39:00 1.6373834  0.6634234 1.7666790898 7200  0.000000  0.3849578          NA N34246@096AFE12
2 14.93837 46.39433 2022-05-03 21:39:00 1.6603166  0.9906000 1.9333751763 7200  3.121155  0.5379402  0.15298242 N34246@096AFE12
3 16.59868 47.38493 2022-05-03 23:39:00 1.4890000  1.0557983 1.8253303948 7200 13.610619  0.6167842  0.07884398 N34246@096AFE12
4 18.08768 48.44073 2022-05-04 01:39:00 0.4750167  0.2986600 0.5611048573 7200 30.255631  0.5612812 -0.05550300 N34246@096AFE12
5 18.56270 48.73939 2022-05-04 03:39:00 0.0000000 -0.0000850 0.0000850000 7200 36.736625 -1.5707963 -2.13207754 N34246@096AFE12
6 18.56270 48.73931 2022-05-04 05:39:00 0.0000833  0.0001100 0.0001379815 7200 36.736113  0.9226569  2.49345322 N34246@096AFE12
   burst                                         pkey     velocity  turning_angle_x turning_angle_y
1 N34246@096AFE12 [email protected] 19:39:00 2.453721e-04              NA              NA
2 N34246@096AFE12 [email protected] 21:39:00 2.685243e-04      0.15298242              NA
3 N34246@096AFE12 [email protected] 23:39:00 2.535181e-04      0.07884398     -0.07413844
4 N34246@096AFE12 [email protected] 01:39:00 7.793123e-05     -0.05550300     -0.13434698
5 N34246@096AFE12 [email protected] 03:39:00 1.180556e-08     -2.13207754     -2.07657455
6 N34246@096AFE12 [email protected] 05:39:00 1.916410e-08      2.49345322      4.62553077

For reference, the dist between 1 and 2 should be roughly 2099000 m. The dist values are automatically calculated by the adehabitatLT functions.

What am I doing wrong?

Any help is highly appreciated :)


Solution

  • I believe the issue is you are using lat long instead of UTM for your coordinates. "adehabitatLT" dosen't automatically convert lat long into meters.