Fitting CTMM models to videotracked animals

331 views
Skip to first unread message

pennek...@googlemail.com

unread,
May 14, 2018, 5:02:06 AM5/14/18
to ctmm R user group
Dear Christen,

thanks for providing with the CTMM package such a user-friendly tool to perform advanced movement analysis. The vignettes do a great job of explaining the basics and advanced applications, however, I still have some questions that I was unfortunately not able to solve myself.

1) I do not have GPS trajectories, therefore the telemetry object has to be tweaked. I take videos of microorganisms, track them and hence have a coordinate system in micrometers which I get from my tracking software. I was able to turn that into a telemetry object however, the scales are obviously wrong and this may be suboptimal for reporting the parameter estimates. Do you have a preferred way of dealing with such non-georeferenced data sources? Find the code I use to get the data at least processed by CTMM below:

ind$timestamp <- as.POSIXct(ind$timestamp, origin = "1900-01-01", format = "%OS")
ind$lat <- ind$x/100000
ind$long <- ind$y/100000
ind$individual.local.identifier <- ind$uniquetrajectID

datum <- "WGS84"
lon_0 <- stats::median(ind$lat)
lat_0 <- stats::median(ind$lat)
proj <- paste0("+proj=aeqd +lon_0=",lon_0," +lat_0=",lat_0," +datum=",datum)
ind_tele <- as.telemetry(ind[, -c(13,14)], projection = proj)

2) I have a large number of trajectories (literally tens of thousands) which are however often short. Computationally it may be more convenient to summarize them at the population level first. But how can I perform the model selection on the pooled semi-variogram? The ctmm.select function requires the data time series as input for individuals and all my attempts to perform the fitting of ctmm models to the pooled variograms have failed. I have pasted the code I used below, all visualization work fine (including guessing initial parameter estimates, but I am stuck with fitting the selection of CTMM models to the data. 

SVFs <- lapply(ind_tele, variogram)
mean_SVF <- mean(SVFs)
plot(mean_SVF,fraction=1,level=level)
title("Population variogram")
variogram.fit(mean_SVF, interactive=T)

m.iid <- ctmm(sigma=4 %#% "hectares", error=T)
fit.iid <- ctmm.fit(mean_SVF, CTMM=m.iid)
fitted.mods <- ctmm.select(data=ind_tele, CTMM=m.iid, verbose=T)

3) I have noticed that fitting the movement models with error=T generally much improves the estimated and fitted ctmm model to the data. I do not have any error estimate, but guess my data comes with some error due to the tracking. What would you advise in terms of accounting for error?  

Many thanks for your help and kind regards,

    Frank

Christen Fleming

unread,
May 15, 2018, 6:25:56 PM5/15/18
to ctmm R user group
Hi Frank,

0) I will need to make some patches to better handle these scales with correct units. Right now, everything goes down to meters and seconds, and its not just the labels on the units. Someone once tried to use degrees as their units and with an area of 10^-10 square degrees, my current numDeriv usage didn't like that. Give me a couple of days to fix this.

1) If you have a data frame DF with numeric columns t,x,y, then you can just do:

TEL <- ctmm:::new.telemetry(DF,info=list(identity="critter"))

and that should work. The projection information should only be necessary for exporting to GIS formats, which I don't imagine you doing.

2) There's no way currently in the package to fit at the population level, but that is something in the road map with hierarchical models for population distributions. The mean variogram is more for situations where individual variograms are too noisy to get a sense of what the truth looks like and compare to the individual fits.

3) Without an error estimate, I would be very cautious and make sure that the fitted error estimate makes sense as tracking error. I don't have a feel for micrometer microorganism movement, but I know for pollen grains and other very small inanimate objects under a microscope, they have fairly jittery movement that is not tracking error, but movement from molecular collisions that occurs at very short timescales. If there is genuine movement at scales beyond the frame rate of the video, then there is no way to distinguish that from tracking error.

Best,
Chris
Message has been deleted

Christen Fleming

unread,
May 17, 2018, 7:06:25 PM5/17/18
to ctmm R user group
Hi Frank,

I put the necessary changes into the development branch, which can be installed via devtools::install_github("ctmm-initiative/ctmm") . Tell me if you encounter any bugs.

Your last post got caught in the spam filter. It was supposed to be released and you are supposed to be able to post from now on... but I still don't see your post and its not in the pending box either... so I have no way to read it. Feel free to re-post or email me if there was anything else.

Best,
Chris

pennek...@googlemail.com

unread,
May 18, 2018, 5:28:46 AM5/18/18
to ctmm R user group
Hi Chris,

thank you very much for your kind reply! I hope my use case does not require huge changes to the package. I maintain an R package myself and know how much work this can be.

Re 1) Sounds good, will try that!

Re 2) Thanks for your clarification that fitting on the population level is currently not supported. The hierarchical approach you describe would be quite handy for our dataset, but I imagine that other features demand your attention for the moment. I will continue fitting to the individual level and use the extracted movement parameters such as speed in a hierarchical model.

Re 3) I will carefully validate whether the error estimates make sense for our movement trajectories. I see your example with Brownian motion of pollen grain, however, I believe this is not yet relevant on the scale of our measurements. The microorganisms I deal with are about 30-50 microns long. But there is definitely some error from the tracking, which I have not quantified yet. Will think about ways of doing this.

Looking forward to further explore the world of ctmms! 

Many thanks and all the best,

    Frank

Frank Pennekamp

unread,
May 18, 2018, 7:16:45 AM5/18/18
to ctmm R user group
Hi Chris,

thanks for helping with the issue so quickly. I can now go down to mm scales, however, I still have to use the as.telemetry function with a proj statement to get my data in the proper format for the variogram function and coercing individuals into the telemetry object. If I downscale the x and y further, the variogram function throws an error. Your suggestion of TEL <- ctmm:::new.telemetry(DF,info=list(identity="critter")) did not quite work for me (or I do it wrong).

Please find attached the script that I use for fitting and plotting models, as well as a part of the dataset to help me troubleshoot the problem.

Many thanks,

   Frank





--
You received this message because you are subscribed to a topic in the Google Groups "ctmm R user group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/ctmm-user/B4lhGOR-5fE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to ctmm-user+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ctmm-user/3b3d8ce9-c666-4973-8338-6d9f77555e54%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

movement_trajectories.csv
Reproducible_example_for_CF.R

Christen Fleming

unread,
May 20, 2018, 11:56:00 AM5/20/18
to ctmm R user group
Hi Frank,

The point at which you call ctmm:::new.telemetry() in your code, you have a timestamp column but not a t column. as.telemetry() converts the timestamp, longitude, and latitude into t,x,y, which is why your as.telemetry() worked and new.telemetry() did not. Here is the code I used and was able to make variograms without a projection step:

DT$t <- DT$frame * 0.04 # assuming this is now seconds from 25FPS feed
DT$x <- DT$x / 1E6 # assuming microns, converting to meters
DT$y <- DT$y / 1E6 # assuming microns, converting to meters

DT_list <- split(DT, f = DT$individual.local.identifier)
ind_tele <- lapply(1:length(DT_list), function(x) ctmm:::new.telemetry(DT_list[[x]], info=list(identity=names(DT_list)[x])))

plot(ind_tele,col=rainbow(length(ind_tele)))

SVFS <- lapply(ind_tele,function(tele){variogram(tele,dt=0.04)})
zoom(SVFS[[49]])

I'm not sure if I got the units right on x & y, so tell me if there is any other issue. You want internal numbers in ctmm in SI units of meters and seconds. Then the plots and summaries will come out automatically in pretty units (which you can disable with units=FALSE if you need).

Best,
Chris

pennek...@googlemail.com

unread,
May 24, 2018, 3:25:22 AM5/24/18
to ctmm R user group
Hi Chris,

thanks so much, this works now as desired. I will soon fit ctmms to a larger number of trajectories to get a feel what movement model best represents my data. At that point, I may check in again, if I struggle with technical issues or interpretation.

Many thanks again for your prompt and kind help!

All the best,

   Frank
Reply all
Reply to author
Forward
0 new messages