################################################################# #R script to do an automatic classification of flying and non flying #behavior based on the acceleration data for Eidolon helvum #studies with eobs-tags ################################################################## library(maptools); library(move) ## download the gps and the acceleration data separately from movebank per study ## filenameACC<-"Eidolon helvum; Ghana, Kibi; dry season 2013 [eobs]_acc.csv" #acc file name filenameGPS<-"Eidolon helvum; Ghana, Kibi; dry season 2013 [eobs]_gps.csv" #gps file name outACC<-"Eidolon_Ghana_Kibi_dry_2013_acc&behav.csv" #output acc file name outGPS<-"Eidolon_Ghana_Kibi_dry_2013_gps&behav.csv" #output gps file name accALL<-read.csv(paste0(getwd(),"/",filenameACC)) #read in the acceleration data accALL$timestamp<-as.POSIXct(as.character(accALL$timestamp), format="%Y-%m-%d %H:%M:%OS",tz="UTC") myindACC<-unique(accALL$individual.local.identifier) myindACC gpsMove<-move(paste0(getwd(),"/",filenameGPS)) # read the gps file as moveStack object gpsMoveL<-split(gpsMove) # if several individuals, convert the moveStack into a list myindGPS<-names(gpsMoveL) myindGPS #check if individuals names are the same in acc file as in move object AllInd<-list() for(ind in myindACC){ print(ind) gps <- gpsMoveL[[ind]] acc <- accALL[accALL$individual.local.identifier==ind,] ##creating table with the samples per acc burst accaxes <- strsplit(as.character(acc$eobs.accelerations.raw), split=" ", fixed=T) numberSamples<-length(unlist(accaxes[1])) accaxes2 <- matrix(unlist(accaxes), ncol=numberSamples, byrow=T) colnames(accaxes2) <- paste0("V", 1:numberSamples) acc2 <-data.frame(acc$timestamp) colnames(acc2)<-"timestamp" acc2$timestamp<-as.POSIXct(acc2$timestamp, format="%Y-%m-%d %H:%M:%OS", tz="UTC") acc2$var.y <- NA acc2$var.z <- NA for(j in 1:nrow(accaxes2)){ yax<-as.numeric(accaxes2[j,seq(2,numberSamples,3)]) zax<-as.numeric(accaxes2[j,seq(3,numberSamples,3)]) acc2$var.y[j] <- var(yax) acc2$var.z[j] <- var(zax) } ## clustering via kmeans the variance of the z and y axis myk<-acc2[,c("var.y","var.z")] mykmeans <- kmeans(myk,2) acc2$cluster<-mykmeans$cluster ## determine which cluster is flying or not-flying agmn<-aggregate(acc2$var.z,by=list(acc2$cluster),FUN=min) acc2$activity<-NA if(agmn$x[agmn$Group.1==1]>agmn$x[agmn$Group.1==2]) {acc2$activity[acc2$cluster==1]<-"Flying" ; acc2$activity[acc2$cluster==2]<-"NotFlying"} if(agmn$x[agmn$Group.1==2]>agmn$x[agmn$Group.1==1]) {acc2$activity[acc2$cluster==2]<-"Flying" ; acc2$activity[acc2$cluster==1]<-"NotFlying"} ## assigning day or night to each busts (according to sunset and sunrise) centroidLatLong<-centroid(gps@coords) acc2$long <- centroidLatLong[1] acc2$lat <- centroidLatLong[2] myindSP <- as.matrix(acc2[,c("long","lat")]) datetime <- as.POSIXct(acc2$timestamp, format="%Y-%m-%d %H:%M:%OS", tz="UTC") sunrise<-sunriset(myindSP, datetime, proj4string=CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +towgs84=0,0,0"), direction=c("sunrise"), POSIXct.out=T) acc2$sunrise <- sunrise$time sunset<-sunriset(myindSP, datetime, proj4string= CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +towgs84=0,0,0"), direction=c("sunset"), POSIXct.out=T) acc2$sunset <- sunset$time acc2$DayTime <- ifelse(acc2$timestamp>acc2$sunrise & acc2$timestampagmn$x[agmn$Group.1==2]) {acc2$activity[acc2$cluster==1]<-"Flying" ; acc2$activity[acc2$cluster==2]<-"NotFlying"} if(agmn$x[agmn$Group.1==2]>agmn$x[agmn$Group.1==1]) {acc2$activity[acc2$cluster==2]<-"Flying" ; acc2$activity[acc2$cluster==1]<-"NotFlying"} allaxis$cluster<- as.factor(rep(c(acc2$activity),each=264)) ### plots of the acc data as they appear in the acc viewer of movebank # subset of the 1st 3h of data zz<-allaxis[1:47520,] plot(zz$zaxB,type="l",col="blue") # z axis lines(zz$yaxB,col="green") # y axis lines(zz$xaxB,col="red")# x axis points(zz$zaxB,col=c("black","yellow")[zz$cluster],pch=20,cex=.6) #black is Flying, yellow is NotFlying # subset of 60 min of data somewhere in the middle yy<-allaxis[174240:190080,] plot(yy$zaxB,type="l",col="blue") lines(yy$yaxB,col="green") lines(yy$xaxB,col="red") points(yy$zaxB,col=c("black","yellow")[yy$cluster],pch=20,cex=.6) #black is Flying, yellow is NotFlying #all data plot(allaxis$zaxB,type="l",col="blue") lines(allaxis$yaxB,col="green") lines(allaxis$xaxB,col="red") points(allaxis$zaxB,col=c("black","yellow")[allaxis$cluster],pch=20,cex=.6)